字元裝置驅動筆記

2021-09-22 22:45:59 字數 4187 閱讀 3333

在所有linux裝置驅動中,字元裝置驅動最為基礎,本筆記將講解linux字元裝置驅動的結構,並解釋其主要組成部分的程式設計方法。

cdev結構

struct cdev ;
cdev結構體的dev_t成員定義了裝置號,為32位,其中12bit為主裝置號,20bit為次裝置號。使用如下巨集可以從dev_t獲得主裝置號和次裝置號。

major(dev_t dev)

minor(dev_t dev)

使用如下巨集可以用主裝置號和次裝置號生成裝置號

mkdev(int major, int minor)
核心提供了一組函式用於操作cdev結構體:

void cdev_init(struct cdev *,struct file_operations *);/*初始化cdev成員,建立cdev和file_operations的連線*/  

struct cdev *cdev_alloc(void);/*動態申請乙個cdev記憶體*/

void cdev_put(struct cdev *p);

int cdev_add(struct cdev *, dev_t, unsigned); /*向系統新增乙個cdev*/

void cdev_del(struct cdev *);/*刪除系統中的乙個cdev*/

裝置號的申請和釋放

int register_chrdev_region(dev_t from, unsigned count, const char *name);/*用於已知起始裝置號的情況下申請裝置號*/

int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name);/*用於未知起始裝置號的情況下申請未被占用的裝置號*/

void unregister_chrdev_region(dev_t from, unsigned count);/*設防裝置號*/

file_operations結構

cdev結構體的乙個重要成員file_operations定義了字元裝置驅動提供給檔案系統的介面函式。

struct file_operations ;
如下是乙個最簡單的字元裝置驅動,四個led燈的控制,可以作為字元裝置驅動的模板。

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int led_major = 0;     /* 主裝置號 */

static struct cdev leddevs;

/* 應用程式執行ioctl(fd, cmd, arg)時的第2個引數 */

#define led_magic 'k'

#define ioctl_led_on _iow (led_magic, 1, int)

#define ioctl_led_off _iow (led_magic, 2, int)

#define ioctl_led_run _iow (led_magic, 3, int)

#define ioctl_led_shine _iow (led_magic, 4, int)

#define ioctl_led_allon _iow (led_magic, 5, int)

#define ioctl_led_alloff _iow (led_magic, 6, int)

/* 用來指定led所用的gpio引腳 */

static unsigned long led_table = ;

/* 應用程式對裝置檔案/dev/led執行open(...)時,

* 就會呼叫s3c24xx_leds_open函式

*/static int s3c2440_leds_open(struct inode *inode, struct file *file)

return 0;

}//leds all light on

void leds_all_on()

}//leds all light off

void leds_all_off()

}/* 應用程式對裝置檔案/dev/leds執行ioctl(...)時,

* 就會呼叫s3c24xx_leds_ioctl函式

*/static int s3c2440_leds_ioctl(struct inode *inode,

struct file *file,

unsigned int cmd,

unsigned long arg)

/* * 執行「insmod s3c24xx_leds.ko」命令時就會呼叫這個函式

*/static int __init s3c2440_leds_init(void)

if (result < 0)

if (led_major == 0)

led_major = result;

/* now set up cdev. */

led_setup_cdev(&leddevs, 0, &s3c2440_leds_fops);

printk("led device installed, with major %d\n", led_major);

printk("the device name is: %s\n", dev_name);

return 0;}/*

* 執行」rmmod s3c24xx_leds」命令時就會呼叫這個函式

*/static void __exit s3c2440_leds_exit(void)

/* 這兩行指定驅動程式的初始化函式和解除安裝函式 */

module_init(s3c2440_leds_init);

module_exit(s3c2440_leds_exit);

/* 描述驅動程式的一些資訊,不是必須的 */

module_author("eurphan"); // 驅動程式的作者

module_description("s3c2440 led driver"); // 一些描述資訊

module_license("dual bsd/gpl"); // 遵循的協議

寫好的驅動怎麼測試呢,這就需要編寫應用程式來測試了

#include #include #include #include #define led_magic 'k'

#define ioctl_led_on _iow (led_magic, 1, int)

#define ioctl_led_off _iow (led_magic, 2, int)

#define ioctl_led_run _iow (led_magic, 3, int)

#define ioctl_led_shine _iow (led_magic, 4, int)

#define ioctl_led_allon _iow (led_magic, 5, int)

#define ioctl_led_alloff _iow (led_magic, 6, int)

void usage(char *exename)

int main(int argc, char **ar**)

if (argc == 2) else if (!strcmp(ar**[1], "off")) else if (!strcmp(ar**[1], "run")) else if (!strcmp(ar**[1], "shine")) else

} if (argc == 3) else if (!strcmp(ar**[2], "off")) else

}

close(fd);

return 0;

err:

if (fd > 0)

close(fd);

usage(ar**[0]);

return -1;

}

字元裝置驅動筆記(二)

怎麼寫led驅動 寫框架 完善硬體的操作 1 看原理圖 2 看2440手冊 3 微控制器 直接操作實體地址 驅動程式 操作虛擬位址,實體地址用iorremap對映為虛擬位址 myleds.c include include include include include include includ...

字元裝置驅動筆記(二)

怎麼寫led驅動 寫框架 完善硬體的操作 1 看原理圖 2 看2440手冊 3 微控制器 直接操作實體地址 驅動程式 操作虛擬位址,實體地址用iorremap對映為虛擬位址 myleds.c include include include include include include includ...

Linux裝置驅動筆記 字元裝置驅動程式

關鍵字 編寫linux字元裝置驅動程式 linux提供了幾種註冊字元裝置的方式。如下 include include include include define dev major 100 define dev name test static intmyopen struct inode ino...