kernel下的设备分成了一些类,char block char。。
这里就贴出来一个样例能够建立一个char设备 ,抛砖引玉吧
这是kernel中的 drivers/char/msm_smd_pkt.c
先要启动初始化module
module_init(smd_pkt_init);
smd_pkt_init会在启动之后调用
static int __init smd_pkt_init(void)
{ int i; int r; 创造char设备的结构体 r = alloc_chrdev_region(&smd_pkt_number, 0, NUM_SMD_PKT_PORTS, DEVICE_NAME); if (r) { pr_err("alloc_chrdev_region() failed %d\n", r); return r; } 创造class下的设备机构提 smd_pkt_classp = class_create(THIS_MODULE, DEVICE_NAME); if (IS_ERR(smd_pkt_classp)) { r = PTR_ERR(smd_pkt_classp); pr_err("class_create() failed %d\n", r); goto unreg_chardev; } for (i = 0; i < NUM_SMD_PKT_PORTS; ++i) { smd_pkt_devp[i] = kzalloc(sizeof(struct smd_pkt_dev), GFP_KERNEL); if (IS_ERR(smd_pkt_devp[i])) { r = PTR_ERR(smd_pkt_devp[i]); pr_err("kmalloc() failed %d\n", r); goto clean_cdevs; } smd_pkt_devp[i]->i = i; 以下几行都是私有数据的赋值 我们不用关心 不须要能够删掉 init_waitqueue_head(&smd_pkt_devp[i]->ch_read_wait_queue); smd_pkt_devp[i]->remote_open = 0; init_waitqueue_head(&smd_pkt_devp[i]->ch_opened_wait_queue); mutex_init(&smd_pkt_devp[i]->ch_lock); mutex_init(&smd_pkt_devp[i]->rx_lock); mutex_init(&smd_pkt_devp[i]->tx_lock); 关键地方就是这里了:char设备的结构初始化
cdev_init(&smd_pkt_devp[i]->cdev, &smd_pkt_fops);
smd_pkt_devp[i]->cdev.owner = THIS_MODULE; char设备添加 r = cdev_add(&smd_pkt_devp[i]->cdev, (smd_pkt_number + i), 1); if (r) { pr_err("cdev_add() failed %d\n", r); kfree(smd_pkt_devp[i]); goto clean_cdevs; }char设备在dev下创造一个节点设备 这个一定要有哦 smd_pkt_devp[i]->devicep = device_create(smd_pkt_classp, NULL, (smd_pkt_number + i), NULL, smd_pkt_dev_name[i]); if (IS_ERR(smd_pkt_devp[i]->devicep)) { r = PTR_ERR(smd_pkt_devp[i]->devicep); pr_err("device_create() failed %d\n", r); cdev_del(&smd_pkt_devp[i]->cdev); kfree(smd_pkt_devp[i]); goto clean_cdevs; } } pr_info("SMD Packet Port Driver Initialized.\n"); return 0; 后面就是错误处理了 无论了 clean_cdevs: if (i > 0) { while (--i >= 0) { mutex_destroy(&smd_pkt_devp[i]->ch_lock); mutex_destroy(&smd_pkt_devp[i]->rx_lock); mutex_destroy(&smd_pkt_devp[i]->tx_lock); cdev_del(&smd_pkt_devp[i]->cdev); kfree(smd_pkt_devp[i]); device_destroy(smd_pkt_classp, MKDEV(MAJOR(smd_pkt_number), i)); } } class_destroy(smd_pkt_classp); unreg_chardev: unregister_chrdev_region(MAJOR(smd_pkt_number), NUM_SMD_PKT_PORTS); return r; }