fasync例程分析

代码取自《深入Linux设备驱动程序内核机制》7.7 7.8

app 代码如下:

 1 #include <stdio.h>
 2 #include <sys/types.h>
 3 #include <sys/stat.h>
 4 #include <fcntl.h>
 5 #include <unistd.h>
 6 #include <signal.h>
 7 
 8 #define DEVFILE "/dev/fa_dev"
 9 static unsigned long eflag = 1;
10 
11 static void sigio_handler(int sigio)
12 {
13         printf("Get the SIGIO signal,we exit the application!\n");
14         eflag = 0;
15 }
16 
17 static int block_sigio(void)
18 {
19         sigset_t set,old;
20         int ret;
21 
22         sigemptyset(&set);
23         sigaddset(&set,SIGIO);
24         sigprocmask(SIG_BLOCK,&set,&old);
25         ret = sigismember(&old,SIGIO);
26 
27         return ret;
28 }
29 
30 static void unblock_sigio(int blocked)
31 {
32         sigset_t set;
33         if(!blocked)
34         {
35                 sigemptyset(&set);
36                 sigaddset(&set,SIGIO);
37                 sigprocmask(SIG_UNBLOCK,&set,NULL);
38         }
39 }
40 
41 int main(void)
42 {
43         int fd;
44         struct sigaction sigact,oldact;
45 
46         int oflag;
47         int blocked;
48 
49         blocked = block_sigio();
50 
51         sigemptyset(&sigact.sa_mask);
52         sigaddset(&sigact.sa_mask,SIGIO);
53         sigact.sa_flags = 0;
54         sigact.sa_handler = sigio_handler;
55 
56         if(sigaction(SIGIO,&sigact,&oldact)<0)
57         {
58                 printf("sigaction failded !\n");
59                 unblock_sigio(blocked);
60                 return -1;
61         }
62 
63         unblock_sigio(blocked);
64 
65         fd = open(DEVFILE,O_RDWR);
66         if(fd>=0)
67         {
68                 fcntl(fd,F_SETOWN,getpid());
69                 oflag = fcntl(fd,F_GETFL);
70                 fcntl(fd,F_SETFL,oflag|FASYNC);
71                 printf("Do everything you want until we get a signal...\n");
72                 while(eflag);
73                 close(fd);
74         }
75 
76         return 0;
77 }

上面代码中block_sigio()个人认为逻辑上有问题:

根据:http://learn.akae.cn/media/ch33s03.html所述:

int sigprocmask(int how, const sigset_t *set, sigset_t *oset);如果osetset都是非空指针,则先将原来的信号屏蔽字备份到oset里,然后根据sethow参数更改信号屏蔽字。

个人认为改成如下逻辑更合理:

static int block_sigio(void)
{
        sigset_t set,current;
        int ret;

        sigemptyset(&set);
        sigaddset(&set,SIGIO);
        //首先阻塞SIGIO信号
        sigprocmask(SIG_BLOCK,&set,NULL);
        //再次调用sigprocmask,取得当前信号集current
        sigprocmask(SIG_BLOCK,NULL,&current);
        //判断SIGIO是否在当前信号集中,存在返回1,否则返回0
        ret = sigismember(&current,SIGIO);

        return ret;
}

我不理解原例子中的代码,为什么通过设置了SIGIO信号之前的信号集来做判断条件。

同时unblock_sigio()改为:

static void unblock_sigio(int blocked)
{
        sigset_t set;
        if(blocked)//修改一下
        {
                sigemptyset(&set);
                sigaddset(&set,SIGIO);
                sigprocmask(SIG_UNBLOCK,&set,NULL);
        }
}

附上驱动代码:

 1 #include <linux/module.h>
 2 #include <linux/kernel.h>
 3 #include <linux/fs.h>
 4 #include <linux/cdev.h>
 5 #include <linux/device.h>
 6 #include <asm/signal.h>
 7 #include <asm/siginfo.h>
 8 
 9 static struct cdev *pcdev;
10 static dev_t ndev;
11 static struct class *fa_cls;
12 static struct device *fadev;
13 
14 static unsigned long flag = 0;
15 static struct fasync_struct *sigio_list;
16 
17 
18 static ssize_t read_flag(struct device *dev,struct device_attribute *attr,char *buf)
19 {
20         size_t count = 0;
21         count += sprintf(&buf[count],"%lu\n",flag);
22 
23         return count;
24 }
25 
26 static ssize_t write_flag(struct device *dev,struct device_attributer *attr,
27                                                         const char *buf,size_t count)
28 {
29         flag = buf[0] - '0';
30 
31         kill_fasync(&sigio_list,SIGIO,POLL_IN);
32         return count;
33 }
34 
35 static struct device_attribute flag_attr =
36         __ATTR(flag_file,S_IRUGO|S_IWUSR,read_flag,write_flag);
37 
38 static int fa_open(struct inode *inode,struct file *flp)
39 {
40         return 0;
41 }
42 
43 static int fa_async(int fd,struct file *filp,int onflag)
44 {
45         return fasync_helper(fd,filp,onflag,&sigio_list);
46 }
47 
48 static struct file_operations ops={
49         .owner = THIS_MODULE,
50         .open = fa_open,
51         .fasync = fa_async,
52 };
53 
54 static int fa_init(void)
55 {
56         int ret = 0;
57 
58         ret = alloc_chrdev_region(&ndev,0,1,"fa_dev");
59         if(ret < 0)
60                 return ret;
61 
62         pcdev = cdev_alloc();
63         cdev_init(pcdev,&ops);
64         pcdev->owner = THIS_MODULE;
65         cdev_add(pcdev,ndev,1);
66 
67         fa_cls = class_create(THIS_MODULE,"fa_dev");
68         if(IS_ERR(fa_cls))
69                 return PTR_ERR(fa_cls);
70 
71         fadev = device_create(fa_cls,NULL,ndev,NULL,"fa_dev");
72         if(IS_ERR(fadev))
73                 return PTR_ERR(fadev);
74 
75         ret = device_create_file(fadev,&flag_attr);
76 
77         return ret;
78 }
79 
80 static void fa_exit(void)
81 {
82         device_remove_file(fadev,&flag_attr);
83         device_destroy(fa_cls,ndev);
84         class_destroy(fa_cls);
85         cdev_del(pcdev);
86         unregister_chrdev_region(ndev,1);
87 }
88 
89 module_init(fa_init);
90 module_exit(fa_exit);
91 MODULE_LICENSE("GPL");

 Makefile如下:

export ARCH=x86
export CROSS_COMPILE=
obj-m := fasync_demo.o
KERNELDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
        rm -f *.o *.ko *.mod.*

 

posted @ 2013-06-26 13:55  bob-ding  阅读(256)  评论(0编辑  收藏  举报