《LINUX设备驱动程序》学习之信号量实例
2012-10-31 17:34 Chung-shu 阅读(382) 评论(0) 收藏 举报1. 在上一个globalvar模块的基础上,添加信号量机制,globalvar.c代码如下:
#include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/uaccess.h> #include <linux/slab.h> #include <linux/semaphore.h> #include <linux/random.h> #include <linux/delay.h> MODULE_LICENSE("GPL"); int globalvar_open(struct inode *, struct file *); int globalvar_release(struct inode *, struct file *); ssize_t globalvar_read(struct file *, char *, size_t, loff_t *); ssize_t globalvar_write(struct file *, const char *, size_t, loff_t *); int dev_major=0; int dev_minor=0; struct file_operations globalvar_fos= { .owner=THIS_MODULE, .open=globalvar_open, .release=globalvar_release, .read=globalvar_read, .write=globalvar_write, }; struct globalvar_dev { int global_var; //代表要操作的设备 struct cdev cdev; //内核中表示字符设备的结构 struct semaphore sem; //互斥信号量 }; struct globalvar_dev *my_dev; static void __exit globalvar_exit(void) //退出模块时的操作 { dev_t devno=MKDEV(dev_major, dev_minor); cdev_del(&my_dev->cdev); //从系统中移除一个字符设备 kfree(my_dev); //释放自定义的设备结构 unregister_chrdev_region(devno, 1); //注销已注册的驱动程序 printk("globalvar unregister success!\n"); } static int __init globalvar_init(void) //初始化模块的操作 { int ret, err; dev_t devno=MKDEV(dev_major, dev_minor); //注册设备号 if(dev_major) { ret=register_chrdev_region(devno, 1, "globalvar"); } else { ret=alloc_chrdev_region(&devno, dev_minor, 1, "globalvar"); dev_major=MAJOR(devno); } if(ret<0) { printk("globalvar register failure!\n"); globalvar_exit(); //如果注册设备号失败就退出。这个有问题? return ret; } else { printk("globalvar register success!\n"); } //为设备分配内核空间 my_dev=kmalloc(sizeof(struct globalvar_dev), GFP_KERNEL); if(!my_dev) { ret=-ENOMEM; printk("create device failed!\n"); } else //初始化设备,添加设备 { my_dev->global_var=0; //设备变量初始化为0 sema_init(&my_dev->sem, 1); //初始化信号量 cdev_init(&my_dev->cdev, &globalvar_fos); //初始化设备中的cdev结构 my_dev->cdev.owner=THIS_MODULE; //初始化cdev中的所有者字段 //向内核添加cdev结构,注意到此时用到了devno err=cdev_add(&my_dev->cdev, devno, 1); if(err<0) //如果添加字符设备失败,打印错误信息 printk("add charater device failure!\n"); else printk("add charater device success!\n"); } return ret; } //打开操作 int globalvar_open(struct inode *inode, struct file *filp) { struct globalvar_dev *dev; //根据inode结构的cdev字段,获得整个设备结构的指针 dev=container_of(inode->i_cdev, struct globalvar_dev, cdev); //分配并填写置于filp->private_data里的数据结构,private_data是跨系统调用时 //保存状态信息的非常有用的资源 filp->private_data=dev; return 0; } //释放操作 int globalvar_release(struct inode *inode, struct file *filp) { //为什么不释放filp->private_data??? return 0; } //读操作 ssize_t globalvar_read(struct file *filp, char *buf, size_t len, loff_t *off) { int random_int, random_int_msec; struct globalvar_dev *dev=filp->private_data; //获取已指向分配数据的指针 //获取信号量 if(down_interruptible(&dev->sem)) return -ERESTARTSYS; //将设备变量值复制到用户空间 if(copy_to_user(buf, &dev->global_var, sizeof(int))) return -EFAULT; //获取一个随机整数 get_random_bytes(&random_int, sizeof(int)); random_int_msec=random_int%500+500; printk("random_int_msec is %d.\n",random_int_msec); //让进程忙等待随机时间,模拟设备忙 mdelay(random_int_msec); //释放信号量 up(&dev->sem); return sizeof(int); //返回读取数据字节数 } //写操作 ssize_t globalvar_write(struct file *filp, const char *buf, size_t len, loff_t *off) { struct globalvar_dev *dev=filp->private_data; //获取已指向分配数据的指针 //将用户空间值复制到设备变量 if(copy_from_user(&dev->global_var, buf, sizeof(int))) return -EFAULT; return sizeof(int); } module_init(globalvar_init); module_exit(globalvar_exit);
2. 编写测试程序,代码如下:
#include <unistd.h> #include <sys/types.h> #include <stdio.h> #include <errno.h> #include <sys/stat.h> #include <fcntl.h> extern int errno; int main(void) { pid_t i, child; for(i=0;i<5;i++) { child=fork(); if(child==0||child==-1)break; } //进程创建错误 if(child==-1) { printf("Fork error:%s.\n",strerror(errno)); return -1; } else if(child==0) //子进程 { int fd, j, num=3; //只读方式打开设备 fd=open("/dev/globalvar", O_RDONLY, S_IRWXU|S_IRWXG); if(fd==-1) { printf("Device open failure!\n"); return -1; } for(j=0;j<20;j++) { if(read(fd, &num, sizeof(int))==-1) //读取设备变量 printf("Child process NO.%d error:%s.\n", getpid(), strerror(errno)); else printf("Child process NO.%d:The globalvar is %d.\n", getpid(), num); } close(fd); //关闭设备文件 } else //父进程 { int fd, j, num=3; //只读方式打开设备 fd=open("/dev/globalvar", O_RDONLY, S_IRWXU|S_IRWXG); if(fd==-1) { printf("Device open failure!\n"); return -1; } for(j=0;j<20;j++) { if(read(fd, &num, sizeof(int))==-1) //读取设备变量 printf("Parent process NO.%d error:%s.\n", getpid(), strerror(errno)); else printf("Parent process NO.%d:The globalvar is %d.\n", getpid(), num); } close(fd); //关闭设备文件 } return 0; }
3. 运行结果
1 Parent process NO.2492:The globalvar is 0. 2 Child process NO.2496:The globalvar is 0. 3 Child process NO.2497:The globalvar is 0. 4 Child process NO.2494:The globalvar is 0. 5 Child process NO.2495:The globalvar is 0. 6 Child process NO.2493:The globalvar is 0. 7 Parent process NO.2492:The globalvar is 0. 8 Child process NO.2496:The globalvar is 0. 9 Child process NO.2497:The globalvar is 0. 10 Child process NO.2494:The globalvar is 0. 11 Child process NO.2495:The globalvar is 0. 12 Child process NO.2493:The globalvar is 0. 13 Parent process NO.2492:The globalvar is 0. 14 Child process NO.2496:The globalvar is 0. 15 Child process NO.2497:The globalvar is 0. 16 Child process NO.2494:The globalvar is 0. 17 Child process NO.2495:The globalvar is 0. 18 Child process NO.2493:The globalvar is 0. 19 Parent process NO.2492:The globalvar is 0. 20 Child process NO.2496:The globalvar is 0. 21 Child process NO.2497:The globalvar is 0. 22 Child process NO.2494:The globalvar is 0. 23 Child process NO.2495:The globalvar is 0. 24 Child process NO.2493:The globalvar is 0. 25 Parent process NO.2492:The globalvar is 0. 26 Child process NO.2496:The globalvar is 0. 27 Child process NO.2497:The globalvar is 0. 28 Child process NO.2494:The globalvar is 0. 29 Child process NO.2495:The globalvar is 0. 30 Child process NO.2493:The globalvar is 0. 31 Parent process NO.2492:The globalvar is 0. 32 Child process NO.2496:The globalvar is 0. 33 Child process NO.2497:The globalvar is 0. 34 Child process NO.2494:The globalvar is 0. 35 Child process NO.2495:The globalvar is 0. 36 Child process NO.2493:The globalvar is 0. 37 Parent process NO.2492:The globalvar is 0. 38 Child process NO.2496:The globalvar is 0. 39 Child process NO.2497:The globalvar is 0. 40 Child process NO.2494:The globalvar is 0. 41 Child process NO.2495:The globalvar is 0. 42 Child process NO.2493:The globalvar is 0. 43 Parent process NO.2492:The globalvar is 0. 44 Child process NO.2496:The globalvar is 0. 45 Child process NO.2497:The globalvar is 0. 46 Child process NO.2494:The globalvar is 0. 47 Child process NO.2495:The globalvar is 0. 48 Child process NO.2493:The globalvar is 0. 49 Parent process NO.2492:The globalvar is 0. 50 Child process NO.2496:The globalvar is 0. 51 Child process NO.2497:The globalvar is 0. 52 Child process NO.2494:The globalvar is 0. 53 Child process NO.2495:The globalvar is 0. 54 Child process NO.2493:The globalvar is 0. 55 Parent process NO.2492:The globalvar is 0. 56 Child process NO.2496:The globalvar is 0. 57 Child process NO.2497:The globalvar is 0. 58 Child process NO.2494:The globalvar is 0. 59 Child process NO.2495:The globalvar is 0. 60 Child process NO.2493:The globalvar is 0. 61 Parent process NO.2492:The globalvar is 0. 62 Child process NO.2496:The globalvar is 0. 63 Child process NO.2497:The globalvar is 0. 64 Child process NO.2494:The globalvar is 0. 65 Child process NO.2495:The globalvar is 0. 66 Child process NO.2493:The globalvar is 0. 67 Parent process NO.2492:The globalvar is 0. 68 Child process NO.2496:The globalvar is 0. 69 Child process NO.2497:The globalvar is 0. 70 Child process NO.2494:The globalvar is 0. 71 Child process NO.2495:The globalvar is 0. 72 Child process NO.2493:The globalvar is 0. 73 Parent process NO.2492:The globalvar is 0. 74 Child process NO.2496:The globalvar is 0. 75 Child process NO.2497:The globalvar is 0. 76 Child process NO.2494:The globalvar is 0. 77 Child process NO.2495:The globalvar is 0. 78 Child process NO.2493:The globalvar is 0. 79 Parent process NO.2492:The globalvar is 0. 80 Child process NO.2496:The globalvar is 0. 81 Child process NO.2497:The globalvar is 0. 82 Child process NO.2494:The globalvar is 0. 83 Child process NO.2495:The globalvar is 0. 84 Child process NO.2493:The globalvar is 0. 85 Parent process NO.2492:The globalvar is 0. 86 Child process NO.2496:The globalvar is 0. 87 Child process NO.2497:The globalvar is 0. 88 Child process NO.2494:The globalvar is 0. 89 Child process NO.2495:The globalvar is 0. 90 Child process NO.2493:The globalvar is 0. 91 Parent process NO.2492:The globalvar is 0. 92 Child process NO.2496:The globalvar is 0. 93 Child process NO.2497:The globalvar is 0. 94 Child process NO.2494:The globalvar is 0. 95 Child process NO.2495:The globalvar is 0. 96 Child process NO.2493:The globalvar is 0. 97 Parent process NO.2492:The globalvar is 0. 98 Child process NO.2496:The globalvar is 0. 99 Child process NO.2497:The globalvar is 0. 100 Child process NO.2494:The globalvar is 0. 101 Child process NO.2495:The globalvar is 0. 102 Child process NO.2493:The globalvar is 0. 103 Parent process NO.2492:The globalvar is 0. 104 Child process NO.2496:The globalvar is 0. 105 Child process NO.2497:The globalvar is 0. 106 Child process NO.2494:The globalvar is 0. 107 Child process NO.2495:The globalvar is 0. 108 Child process NO.2493:The globalvar is 0. 109 Parent process NO.2492:The globalvar is 0. 110 Child process NO.2496:The globalvar is 0. 111 Child process NO.2497:The globalvar is 0. 112 Child process NO.2494:The globalvar is 0. 113 Child process NO.2495:The globalvar is 0. 114 Child process NO.2493:The globalvar is 0. 115 Parent process NO.2492:The globalvar is 0. 116 Child process NO.2496:The globalvar is 0. 117 Child process NO.2497:The globalvar is 0. 118 Child process NO.2494:The globalvar is 0. 119 Child process NO.2495:The globalvar is 0. 120 Child process NO.2493:The globalvar is 0.
这让我很困惑,为什么没有发生竞争现象?
浙公网安备 33010602011771号