注册设备号例子

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/sched.h> 
#include <linux/kernel.h>	/* printk(), min() */
#include <linux/slab.h>		/* kmalloc() */
#include <linux/fs.h>		/* everything... */
#include <linux/proc_fs.h>
#include <linux/errno.h>	/* error codes */
#include <linux/types.h>	/* size_t */
#include <linux/fcntl.h>
#include <linux/poll.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>


struct scull_pipe {
        wait_queue_head_t inq, outq;       /* read and write queues */
        char *buffer, *end;                /* begin of buf, end of buf */
        int buffersize;                    /* used in pointer arithmetic */
        char *rp, *wp;                     /* where to read, where to write */
        int nreaders, nwriters;            /* number of openings for r/w */
        struct fasync_struct *async_queue; /* asynchronous readers */
        struct semaphore sem;              /* mutual exclusion semaphore */
        struct cdev cdev;                  /* Char device structure */
};
struct file_operations scull_pipe_fops = {
	.owner =	THIS_MODULE,
/*	.llseek =	no_llseek,
	.read =		scull_p_read,
	.write =	scull_p_write,
	.poll =		scull_p_poll,
	.ioctl =	scull_ioctl,
	.open =		scull_p_open,
	.release =	scull_p_release,
	.fasync =	scull_p_fasync,
*/
};
dev_t firstdev=260046855;/*major=248 minor=7*/
dev_t  devno=260046855;
struct scull_pipe *mydevice;
int err;
int scull_p_init(void)
{	
	int  result;
	printk(KERN_INFO"Hello, KERN_INFO !\n");  
	printk(KERN_INFO"Hello, shit !\n");  
	result = register_chrdev_region(firstdev, 1, "song");
	printk("firstdev=%d\n",firstdev);
	printk("MAJOR=%d\n",MAJOR(firstdev));
	printk("MINOR=%d\n",MINOR(firstdev));
	if (result < 0) {
		printk(KERN_NOTICE "Unable to get scullp region, error %d\n", result);
		return 0;
	}


	mydevice=kmalloc(sizeof(struct scull_pipe),GFP_KERNEL);
	cdev_init(&mydevice->cdev, &scull_pipe_fops);
	mydevice->cdev.owner = THIS_MODULE;
	err = cdev_add (&mydevice->cdev, firstdev, 1);
	if (err)
		printk(KERN_NOTICE "Error %d adding scullpipe", err);
/**********************************************************************************/
	firstdev++;/*major=248 minor=8*/
	result = register_chrdev_region(firstdev, 2, "hi");//minor=8,9
	printk("firstdev=%d\n",firstdev);
	printk("MAJOR=%d\n",MAJOR(firstdev));
	printk("MINOR=%d\n",MINOR(firstdev));
	if (result < 0) {
		printk(KERN_NOTICE "Unable to get scullp region, error %d\n", result);
		return 0;
	}

}


/*
 * This is called by cleanup_module or on failure.
 * It is required to never fail, even if nothing was initialized first
 */
void scull_p_cleanup(void)
{	
	printk("<4>Good-bye\n");  	
	unregister_chrdev_region(devno, 3);
/*	

*/
}

module_init(scull_p_init);  
module_exit(scull_p_cleanup);  
MODULE_LICENSE("GPL");  
[root@localhost test]# make
[root@localhost test]# insmod test.ko
[root@localhost test]# cat /proc/devices 
Character devices:
  1 mem
  4 /dev/vc/0
  4 tty
  4 ttyS
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
  6 lp
  7 vcs
 10 misc
 13 input
 14 sound
 21 sg
 29 fb
 68 capi20
 99 ppdev
116 alsa
128 ptm
136 pts
162 raw
180 usb
189 usb_device
202 cpu/msr
203 cpu/cpuid
248 song
248 hi
249 capi
250 vmci
251 hidraw
252 usbmon
253 bsg
254 rtc
看来已经注册成功,三个设备号,第一次注册1个,第二次注册2个
每成功register_chrdev_region一次,就会在/proc/devices里添加一条记录
1.每次register可以注册一个主设备号,但可以多个次设备号
2.多次register时,主设备号可以相同,但次设备号不要相同
3.多次register时,设备名可以相同
[root@localhost test]# dmsg
...
[  338.162180] Hello, KERN_INFO !
[  338.162431] Hello, shit !
[  338.162694] firstdev=260046855
[  338.162705] MAJOR=248
[  338.162715] MINOR=7
[  338.179109] firstdev=260046856
[  338.179120] MAJOR=248
[  338.179130] MINOR=8
[  338.179196] sys_init_module: 'test'->init suspiciously returned 26, it should follow 0/-E convention
[  338.179198] sys_init_module: loading module anyway...
[  338.179321] Pid: 3101, comm: insmod Not tainted 2.6.35.6-45.fc14.i686 #1
[  338.179350] Call Trace:
[  338.179828]  [<c07a56f1>] ? printk+0x25/0x2c
[  338.179990]  [<c0462211>] sys_init_module+0xec/0x19b
[  338.180004]  [<c07a73ac>] syscall_call+0x7/0xb



好的,下面是一个使用`register_chrdev`函数注册字符设备例子: ```c #include <linux/module.h> #include <linux/fs.h> #include <linux/uaccess.h> // 定义设备 static dev_t devno; // 定义字符设备结构体 static struct cdev cdev; // 打开设备 static int example_open(struct inode *inode, struct file *filp) { printk(KERN_INFO "example device opened\n"); return 0; } // 释放设备 static int example_release(struct inode *inode, struct file *filp) { printk(KERN_INFO "example device released\n"); return 0; } // 读取设备 static ssize_t example_read(struct file *filp, char __user *buf, size_t len, loff_t *off) { char *kbuf = "Hello, world!\n"; int ret; if (*off >= strlen(kbuf)) { return 0; } ret = copy_to_user(buf, kbuf + *off, strlen(kbuf) - *off); if (ret != 0) { printk(KERN_ERR "copy_to_user failed\n"); return -EFAULT; } *off += len; return len; } // 写入设备 static ssize_t example_write(struct file *filp, const char __user *buf, size_t len, loff_t *off) { char kbuf[1024]; int ret; if (len >= sizeof(kbuf)) { printk(KERN_ERR "buffer too small\n"); return -EINVAL; } ret = copy_from_user(kbuf, buf, len); if (ret != 0) { printk(KERN_ERR "copy_from_user failed\n"); return -EFAULT; } kbuf[len] = '\0'; printk(KERN_INFO "received data: %s\n", kbuf); return len; } // 注册设备操作函数 static const struct file_operations example_fops = { .owner = THIS_MODULE, .open = example_open, .release = example_release, .read = example_read, .write = example_write, }; // 模块加载函数 static int __init example_init(void) { int ret; // 分配设备 ret = alloc_chrdev_region(&devno, 0, 1, "example"); if (ret < 0) { printk(KERN_ERR "alloc_chrdev_region failed\n"); return ret; } // 初始化字符设备 cdev_init(&cdev, &example_fops); cdev.owner = THIS_MODULE; // 注册字符设备 ret = cdev_add(&cdev, devno, 1); if (ret < 0) { printk(KERN_ERR "cdev_add failed\n"); unregister_chrdev_region(devno, 1); return ret; } printk(KERN_INFO "example module loaded\n"); return 0; } // 模块卸载函数 static void __exit example_exit(void) { // 注销字符设备 cdev_del(&cdev); // 释放设备 unregister_chrdev_region(devno, 1); printk(KERN_INFO "example module unloaded\n"); } module_init(example_init); module_exit(example_exit); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("Example character device driver"); MODULE_LICENSE("GPL"); ``` 这个例子实现了一个简单的字符设备,支持读和写操作。在模块加载时,它会使用`alloc_chrdev_region`函数分配一个设备,并将设备操作函数和设备注册到内核中。在模块卸载时,它会将设备从内核中注销,并释放设备
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值