[cpp] view plaincopy
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- struct globalfifo_dev{
- struct cdev cdev ;
- unsigned int current_len ;
- unsigned char mem[GLOBALFIFO_SIZE] ;
- struct semaphore sem ;
- wait_queue_head_t r_wait ;
- wait_queue_head_t w_wait ;
- }
-
- globalfifo_dev *globalfifo_devp ;
-
- int gobalfifo_init(void)
- {
- int ret ;
- dev_t devno = MKDEV(globalfifo_major,0) ;
-
- if(globalfifo_major)
- ret = register_chrdev_region(devno,1,"globalfifo") ;
- else{
- ret = alloc_chrdev_region(&devno,0,1,"globalfifo") ;
- globalfifo_major = MAJOR(devno) ;
- }
- if(dev < 0)
- return ret ;
-
- globalfifo_devp = kmalloc(sizeof(struct globalfifo_dev),GFP_KERNEL) ;
- if(globalfifo_devp){
- ret = -ENOMEM ;
- goto fail_malloc ;
- }
-
- memset(globalfifo_devp,0,sizeof(struct globalfifo_dev)) ;
- globalfifo_setup_dev(globalfifo_devp ,0) ;
-
- init_MUTEX(&globalfifo_devp->sem) ;
- init_waitqueue_head(&globalfifo_devp->r_wait) ;
- init_waitqueue_head(&globalfifo_devp->w_wait) ;
- return 0 ;
-
- fail_malloc :unregister_chrdev_region(devno,1) ;
- return ret ;
- }
-
-
- static ssize_t globalfifo_read(struct file *filp,char __user *buf,
- size_t count ,loff_t *ppos)
- {
- int ret ;
- struct globalfifo_dev *dev = filp->private_data ;
- DECLARE_WAITQUEUE(wait,current) ;
-
- down(&dev->sem) ;
- add_wait_queue(&dev->r_wait,&wait) ;
-
-
- while(dev->current_len == 0){
- if(filp->f_flags & O_NONBLOCK){
- ret = -EAGAIN ;
- goto out ;
- }
-
- __set_current_state(TASK_INTERRUPTIBLE) ;
- up(&dev->sem) ;
-
- schedule() ;
- if(signal_pending(current)){
- ret = -ERESTARTSYS ;
- goto out2 ;
- }
-
- down(&dev->sem) ;
- }
-
-
- if(count >dev->current_len)
- count = dev->current_len ;
-
- if(copy_to_user(buf,dev->mem,count)){
- ret = -EFAULT ;
- goto out ;
- }else{
- memcpy(dev->mem,dev->mem + count,dev->current_len - count);
- dev->current_len -= count ;
- printk(KERN_INFO "read %d bytes,current_len:%d\n",count,dev->current_len) ;
-
- wake_up_interruptible(&dev->w_wait) ;
-
- ret = count ;
- }
-
- out :up(&dev->sem) ;
- out2: remove_wait_queue(&dev->r_wait,&wait) ;
- set_current_state(TASK_RUNNING) ;
- return ret ;
- }
-
-
- static ssize_t globalfifo_write(static file *filp,const char __user *buf,
- size_t count,loff_t *ppos)
- {
- struct globalfifo_dev *dev = filp->private_data ;
- int ret ;
- DECLARE_WAITQUEUE(wait,current) ;
-
- down(&dev->sem) ;
- add_wait_queue(&dev->w_wait,&wait) ;
-
-
- while(dev->current_len == GLOBALFIFO_SIZE){
- if(filp->f_flags & O_NONBLOCK){
-
- ret = -EAGAIN ;
- goto out ;
- }
- __set_current_state(TASK_INTERRUPTIBLE) ;
- up(&dev->sem) ;
-
- schedule() ;
- if(signal_pending(current)){
-
- ret = -ERESTARTSYS ;
- goto out2;
- }
- down(&dev->sem) ;
- }
-
- if(count > GLOBALFIFO_SIZE - dev->current_len)
- count = GLOBALFIFO_SIZE - dev->current_len ;
- if(copy_from_user(dev->mem + dev->current_len,buf,count)){
- ret = -EFAULT ;
- goto out ;
- }else{
- dev->current_len += count ;
- printk(KERN_INFO "write %d bytes ,current_len:%d\n",count,dev->current_len) ;
-
- wake_up_interruptible(&dev->r_wait) ;
-
- ret = count ;
- }
- out : up(&dev->sem) ;
- out2: remove_wait_queue(&dev->w_wait,&wait) ;
- set_current_state(TASK_RUNNING) ;
- return ret ;
- }
[plain] view plaincopy
- 在用户空间验证globalfifo的读写
-
- 1、在globalfifo所在文件夹下运行make命令编译得到globalfifo.ko。接着insmod模块:
-
- hasen@hasen-pc$ sudo su
- hasen@hasen-pc# insmod globalfifo.ko
-
- 2、创建设备文件节点"/dev/globalfifo"
-
- hasen@hasen-pc# mknod /dev/globalfifo c 249 0
-
- 3、启动两个进程,一个进程"cat /dev/globalfifo &"在后台执行,一个进程"echo 字符串 /dev/globalfifo"在前台执行
-
- hasen@hasen-pc# cat /dev/globalfifo &
- hasen@hasen-pc# echo 'hello world!' /dev/globalfifo
-
- 会看到:每当echo进程向/dev/globalfifo写入一串数据,cat进程就立即将该串数据显示出来。