zoukankan      html  css  js  c++  java
  • 驱动开发之select与中断下半部分

    驱动开发之select与中断下半部分:

    中断上半部、下半部:

    1、已知中断应该尽快完成,但是很多时候不能保证中断代码一定会及时完成。
    2、当不能保证中断尽快完成时,内核将曾经的一个中断处理函数分成了两个中断处理函数
      其中中断上半部用来处理紧急事件
      中断下半部用来处理非紧急事件
    3、什么是紧急事件:
          直接操作硬件时
          对时间要求非常敏感
          不能被其他中断打断
    4,中断下半部分类:
            软中断(需要使用软中断号,但是所有的软中断号都被占用了)

            小任务

            工作队列

    小任务:对软中断的二次封装:

    初始化小任务:

    1 void tasklet_init(struct tasklet_struct *t,void (*func)(unsigned long), unsigned long data)
    3 参数1:
    4 参数2:中断下半部处理函数
    5 参数3:给中断下半部处理函数传参的

    调度小任务:

    1 tasklet_schedule(struct tasklet_struct *t);

    什么时候调用下半部?
            在中断上半部处理函数返回前,或者返回后调用。

      1 #include <linux/module.h>
      2 #include <linux/fs.h>
      3 #include <linux/platform_device.h>
      4 #include <linux/device.h>
      5 #include <asm/uaccess.h>
      6 #include <linux/irqreturn.h>
      7 #include <linux/interrupt.h>
      8 #include <linux/sched.h>
      9 
     10 int major;
     11 
     12 struct class *cls;
     13 struct device *devs;
     14 struct resource *res_key2;
     15 struct resource *res_key3;
     16 
     17 int key;
     18 wait_queue_head_t keyq;
     19 int flag = 0;
     20 struct timer_list t;
     21 int glo_irqno;
     22 
     23 struct tasklet_struct ts;
     24 
     25 irqreturn_t fs4412_key_handler(int irqno,void *id)
     26 {
     27     glo_irqno = irqno;
     28     mod_timer(&t,jiffies + 30);
     29     return IRQ_HANDLED;
     30 }
     31 
     32 void fs4412_key_timer_handler(unsigned long data)
     33 {
     34     if(glo_irqno == res_key2->start)
     35         key = 2;
     36     if(glo_irqno == res_key3->start)
     37         key = 3;
     38 //    wake_up(&keyq);
     39     wake_up_interruptible(&keyq);
     40     flag = 1;
     41     tasklet_schedule(&ts);
     42 }
     43 
     44 void fs4412_key_task(unsigned long data)
     45 {
     46     printk("task schedule
    ");
     47 }
     48 
     49 int fs4412_key_open(struct inode *inode ,struct file *filp)
     50 {
     51     return 0;
     52 }
     53 
     54 ssize_t fs4412_key_read(struct file *filp,char __user *ubuf,size_t size,loff_t *off)
     55 {
     56     int ret;
     57     
     58 //    wait_event(keyq,flag != 0);
     59     wait_event_interruptible(keyq,flag != 0);
     60     ret = copy_to_user(ubuf,&key,sizeof(key));
     61 
     62     flag = 0;
     63     return sizeof(key);
     64 }
     65 
     66 struct file_operations fops = {
     67     .owner = THIS_MODULE,
     68     .open = fs4412_key_open,
     69     .read = fs4412_key_read,
     70 };
     71 
     72 int fs4412_key_probe(struct platform_device *pdev)
     73 {
     74     int ret;
     75     printk("match ok
    ");
     76 
     77     major = register_chrdev(0,"key",&fops);
     78     cls = class_create(THIS_MODULE,"key");
     79     devs = device_create(cls,NULL,MKDEV(major,0),NULL,"key");
     80     
     81     res_key2 = platform_get_resource(pdev,IORESOURCE_IRQ,0);//索引interrupts = <>,<>第一个<>
     82     res_key3 = platform_get_resource(pdev,IORESOURCE_IRQ,1);
     83     ret = request_irq(res_key2->start,fs4412_key_handler,IRQF_TRIGGER_FALLING,"key2",NULL);
     84     ret = request_irq(res_key3->start,fs4412_key_handler,IRQF_TRIGGER_FALLING,"key3",NULL);
     85 
     86     init_waitqueue_head(&keyq);
     87 
     88     init_timer(&t);
     89     t.function = fs4412_key_timer_handler;//定时器中断处理函数
     90     add_timer(&t);//让内核认识定时器中断处理函数
     91 
     92     tasklet_init(&ts,fs4412_key_task,0);
     93     return 0;
     94 }
     95 
     96 int fs4412_key_remove(struct platform_device *pdev)
     97 {
     98     del_timer(&t);
     99     free_irq(res_key3->start,NULL);
    100     free_irq(res_key2->start,NULL);
    101     device_destroy(cls,MKDEV(major,0));
    102     class_destroy(cls);
    103     unregister_chrdev(major,"key");
    104     return 0;
    105 }
    106 
    107 struct of_device_id fs4412_dt_tbl[] = {
    108     {
    109         .compatible = "fs4412,key",
    110     },
    111     {},
    112 };
    113 
    114 
    115 struct platform_driver pdrv = {
    116     .driver = {
    117         .name = "fs4412-key",
    118         .of_match_table = fs4412_dt_tbl,
    119     },
    120     .probe = fs4412_key_probe,
    121     .remove = fs4412_key_remove,
    122 };
    123 
    124 module_platform_driver(pdrv);
    125 MODULE_LICENSE("GPL");
    小任务

    工作队列:

    1 INIT_WORK(struct work_struct *,void (*)(struct work_struct *work))
    2 
    3 static inline bool schedule_work(struct work_struct *work) 

    如何选择下半部的使用方法?
        小任务运行在中断上下文中(内核空间),对时间要求敏感
        工作队列运行在进程上下文中(用户空间和内核空间),对时间不敏感

        在工作队列中可以使用等待队列,互斥锁,信号量。小任务不可以。

    1 应用层:
    2 int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set*exceptfds, struct timeval *timeout);
    3 参数1:文件描述符最大值+1
    4 参数2:读表
    5 参数3:写表
    6 参数4:异常表
    7 参数5:超时检测
    8 返回值:出错返回-1,超时返回0,成功返回>0
    9 功能:如果没有就绪的文件描述符则阻塞,如果有就绪的文件描述符则唤醒,唤醒的同时会将未就绪的文件描述符清空。
    1 FD_SET();将指定文件描述符加入表中
    2 FD_ZERO();清空文件描述符表
    3 FD_CLR();删除指定的文件描述符
    4 FD_ISSET();判断fd是否在表中
     1 内核源码分析:
     2 struct file_operations 
     3 {
     4 unsigned int (*poll) (struct file *, struct poll_table_struct *);//被select调用
     5 }
     6 
     7 vi fs/select.c 
     8 找到do_select函数
     9 mask = (*f_op->poll)(f.file, wait);
    10 
    11 poll_initwait(&table); 
    12 
    13 --->void poll_initwait(struct poll_wqueues *pwq) 
    14 { 
    15     init_poll_funcptr(&pwq->pt, __pollwait);
    16     pwq->polling_task = current;//当前进程
    17 } 
    18 
    19 --->static inline void init_poll_funcptr(poll_table *pt, poll_queue_proc qproc) 
    20 { 
    21      pt->_qproc = qproc;//将__pollwait赋值给了_qproc
    22  } 
    23 
    24 如果想要调用__pollwait,需要使用
    25 static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
    26 {
    27      if (p && p->_qproc && wait_address)
    28     p->_qproc(filp, wait_address, p);//调用__pollwait
    29 }
    30 
    31 --->static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p)
    32 {
    33      struct poll_wqueues *pwq = container_of(p, struct poll_wqueues, pt);
    34     struct poll_table_entry *entry = poll_get_entry(pwq); 
    35      if (!entry)
    36     return;
    37     entry->filp = get_file(filp);
    38     entry->wait_address = wait_address;
    39     entry->key = p->_key;
    40      init_waitqueue_func_entry(&entry->wait, pollwake);//唤醒接口
    41     entry->wait.private = pwq;
    42     add_wait_queue(wait_address, &entry->wait);//将等待队列项添加到等待队列中
    43 }
      1 #include <linux/module.h>
      2 #include <linux/fs.h>
      3 #include <linux/platform_device.h>
      4 #include <linux/device.h>
      5 #include <asm/uaccess.h>
      6 #include <linux/irqreturn.h>
      7 #include <linux/interrupt.h>
      8 #include <linux/sched.h>
      9 
     10 int major;
     11 
     12 struct class *cls;
     13 struct device *devs;
     14 struct resource *res_key2;
     15 struct resource *res_key3;
     16 
     17 int key;
     18 wait_queue_head_t keyq;
     19 int flag = 0;
     20 struct timer_list t;
     21 int glo_irqno;
     22 
     23 struct work_struct ws;
     24 
     25 irqreturn_t fs4412_key_handler(int irqno,void *id)
     26 {
     27     glo_irqno = irqno;
     28     mod_timer(&t,jiffies + 30);
     29     return IRQ_HANDLED;
     30 }
     31 
     32 void fs4412_key_timer_handler(unsigned long data)
     33 {
     34     if(glo_irqno == res_key2->start)
     35         key = 2;
     36     if(glo_irqno == res_key3->start)
     37         key = 3;
     38 //    wake_up(&keyq);
     39     wake_up_interruptible(&keyq);
     40     flag = 1;
     41     schedule_work(&ws);
     42 }
     43 
     44 void fs4412_key_work(struct work_struct *work)
     45 {
     46     printk("work schedule
    ");
     47 }
     48 
     49 int fs4412_key_open(struct inode *inode ,struct file *filp)
     50 {
     51     return 0;
     52 }
     53 
     54 ssize_t fs4412_key_read(struct file *filp,char __user *ubuf,size_t size,loff_t *off)
     55 {
     56     int ret;
     57     
     58 //    wait_event(keyq,flag != 0);
     59     wait_event_interruptible(keyq,flag != 0);
     60     ret = copy_to_user(ubuf,&key,sizeof(key));
     61 
     62     flag = 0;
     63     return sizeof(key);
     64 }
     65 
     66 struct file_operations fops = {
     67     .owner = THIS_MODULE,
     68     .open = fs4412_key_open,
     69     .read = fs4412_key_read,
     70 };
     71 
     72 int fs4412_key_probe(struct platform_device *pdev)
     73 {
     74     int ret;
     75     printk("match ok
    ");
     76 
     77     major = register_chrdev(0,"key",&fops);
     78     cls = class_create(THIS_MODULE,"key");
     79     devs = device_create(cls,NULL,MKDEV(major,0),NULL,"key");
     80     
     81     res_key2 = platform_get_resource(pdev,IORESOURCE_IRQ,0);//索引interrupts = <>,<>第一个<>
     82     res_key3 = platform_get_resource(pdev,IORESOURCE_IRQ,1);
     83     ret = request_irq(res_key2->start,fs4412_key_handler,IRQF_TRIGGER_FALLING,"key2",NULL);
     84     ret = request_irq(res_key3->start,fs4412_key_handler,IRQF_TRIGGER_FALLING,"key3",NULL);
     85 
     86     init_waitqueue_head(&keyq);
     87 
     88     init_timer(&t);
     89     t.function = fs4412_key_timer_handler;//定时器中断处理函数
     90     add_timer(&t);//让内核认识定时器中断处理函数
     91 
     92     INIT_WORK(&ws,fs4412_key_work);
     93     return 0;
     94 }
     95 
     96 int fs4412_key_remove(struct platform_device *pdev)
     97 {
     98     del_timer(&t);
     99     free_irq(res_key3->start,NULL);
    100     free_irq(res_key2->start,NULL);
    101     device_destroy(cls,MKDEV(major,0));
    102     class_destroy(cls);
    103     unregister_chrdev(major,"key");
    104     return 0;
    105 }
    106 
    107 struct of_device_id fs4412_dt_tbl[] = {
    108     {
    109         .compatible = "fs4412,key",
    110     },
    111     {},
    112 };
    113 
    114 
    115 struct platform_driver pdrv = {
    116     .driver = {
    117         .name = "fs4412-key",
    118         .of_match_table = fs4412_dt_tbl,
    119     },
    120     .probe = fs4412_key_probe,
    121     .remove = fs4412_key_remove,
    122 };
    123 
    124 module_platform_driver(pdrv);
    125 MODULE_LICENSE("GPL");
    工作队列
     1 #include <stdio.h>
     2 #include <sys/types.h>
     3 #include <sys/stat.h>
     4 #include <fcntl.h>
     5 
     6 int main(int argc, const char *argv[])
     7 {
     8     int fd;
     9 
    10     fd = open("/dev/key",O_RDWR);
    11     if(fd == -1)
    12     {
    13         perror("open");
    14         return -1;
    15     }
    16     
    17     int key;
    18     while(1)
    19     {
    20         read(fd,&key,sizeof(key));
    21         printf("key = %d
    ",key);
    22     }
    23     return 0;
    24 }
    应用层代码

    异步通知(信号操作): 

     1 #include<stdio.h>
     2 #include<sys/types.h>
     3 #include<sys/stat.h>
     4 #include<fcntl.h>
     5 #include<unistd.h>
     6 #include<errno.h>
     7 #include<stdlib.h>
     8 #include<signal.h>
     9 int fd;
    10 char buf[64] = {0};
    11 
    12 void func(int sig)
    13 {
    14     read(fd,buf,sizeof(buf));
    15     printf("%s
    ",buf);
    16 }
    17 
    18 int main(int argc, const char *argv[])
    19 {
    20     
    21     char buf1[64] = {0};
    22     if(mkfifo("./fifo",0664) == -1)
    23     {
    24         if(errno == EEXIST)
    25         {
    26             fd = open("./fifo",O_RDONLY);    
    27         }
    28         else 
    29         {
    30             perror("mkfifo");
    31             exit(1);
    32         }
    33     }
    34     else 
    35     {
    36         fd = open("./fifo",O_RDONLY);
    37     }
    38     
    39     signal(SIGIO,func);
    40 
    41     int flag;
    42     flag = fcntl(fd,F_GETFL);
    43     flag = flag | O_ASYNC;
    44     fcntl(fd,F_SETFL,flag);
    45     fcntl(fd,F_SETOWN,getpid());
    46     while(1)
    47     {
    48         printf("hello
    ");
    49         sleep(1);
    50     }
    51     return 0;
    52 }
    signal_read.c
     1 #include<stdio.h>
     2 #include<sys/types.h>
     3 #include<sys/stat.h>
     4 #include<fcntl.h>
     5 #include<unistd.h>
     6 #include<errno.h>
     7 #include<stdlib.h>
     8 #include<string.h>
     9 
    10 int main(int argc, const char *argv[])
    11 {
    12     int fd;
    13 
    14     char buf[64] = {0};
    15     if(mkfifo("./fifo",0664) == -1)
    16     {
    17         if(errno == EEXIST)
    18         {
    19             fd = open("./fifo",O_WRONLY);    
    20         }
    21         else 
    22         {
    23             perror("mkfifo");
    24             exit(1);
    25         }
    26     }
    27     else 
    28     {
    29         fd = open("./fifo",O_WRONLY);
    30     }
    31 
    32     while(1)
    33     {
    34         fgets(buf,sizeof(buf),stdin);
    35         write(fd,buf,strlen(buf) + 1);
    36     }
    37     return 0;
    38 }
    signal_write.c
    1 应用程序:
    2 int flag;
    3 fd = open("1.txt",O_RDONLY);//一旦打开文件,内核会创建file结构体,其中有一个f_flags成员,此时f_flags = O_RDONLY
    4 flag = fcntl(fd,F_GETFL);//从file结构体中获取O_RDONLY保存到flag变量中
    5 flag |= O_ASYNC;//将O_RDONLY | O_ASYNC保存到flag变量中(flag是自定义的变量不是内核的)
    6 fctnl(fd,F_SETFL,flag);//将O_RDONLY | O_ASYNC保存到file结构体的f_flags成员中,内核会指定如果使用了O_ASYNC属性则默认会使用SIGIO信号
    7 
    8 fcntl(fd,F_SETOWN,getpid());//需要注册信号,但是这个函数只指定了给哪个进程注册,谁在给进程注册信号?内核实现注册功能
     1 内核源码分析:
     2 vi arch/arm/include/uapi/asm/unistd.h
     3 
     4 #define __NR_fcntl (__NR_SYSCALL_BASE+ 55)
     5 
     6 --->__SYSCALL(__NR_fcntl, sys_fcntl)
     7 
     8 --->err = do_fcntl(fd, cmd, arg, f.file);
     9 
    10 --->case F_GETFL: 
    11 err = filp->f_flags;对应了flag = fcntl(fd,F_GETFL);
    12     break;
    13     case F_SETFL:
    14     err = setfl(fd, filp, arg);fctnl(fd,F_SETFL,flag)
    15 
    16 ---> if (((arg ^ filp->f_flags) & FASYNC) && filp->f_op->fasync) {
    17 error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0); 
    18 }    
    19 上层如果执行fctnl(fd,F_SETFL,flag),驱动层可能执行fasync接口,前提是flag |= O_ASYNC;改成flag |= FASYNC;
      1 #include <linux/module.h>
      2 #include <linux/fs.h>
      3 #include <linux/platform_device.h>
      4 #include <linux/device.h>
      5 #include <asm/uaccess.h>
      6 #include <linux/irqreturn.h>
      7 #include <linux/interrupt.h>
      8 #include <linux/sched.h>
      9 #include <linux/poll.h>
     10 
     11 int major;
     12 
     13 struct class *cls;
     14 struct device *devs;
     15 struct resource *res_key2;
     16 struct resource *res_key3;
     17 
     18 int key;
     19 wait_queue_head_t keyq;
     20 int flag = 0;
     21 struct timer_list t;
     22 int glo_irqno;
     23 
     24 struct fasync_struct *fa;
     25 
     26 irqreturn_t fs4412_key_handler(int irqno,void *id)
     27 {
     28     glo_irqno = irqno;
     29     mod_timer(&t,jiffies + 30);
     30     return IRQ_HANDLED;
     31 }
     32 
     33 void fs4412_key_timer_handler(unsigned long data)
     34 {
     35     if(glo_irqno == res_key2->start)
     36         key = 2;
     37     if(glo_irqno == res_key3->start)
     38         key = 3;
     39 //    wake_up(&keyq);
     40     wake_up_interruptible(&keyq);
     41     flag = 1;
     42     
     43     //注册SIGIO信号
     44     kill_fasync(&fa,SIGIO,POLLIN);
     45 }
     46 
     47 int fs4412_key_open(struct inode *inode ,struct file *filp)
     48 {
     49     return 0;
     50 }
     51 
     52 ssize_t fs4412_key_read(struct file *filp,char __user *ubuf,size_t size,loff_t *off)
     53 {
     54     int ret;
     55     
     56 //    wait_event(keyq,flag != 0);
     57     wait_event_interruptible(keyq,flag != 0);
     58     ret = copy_to_user(ubuf,&key,sizeof(key));
     59 
     60     flag = 0;
     61     return sizeof(key);
     62 }
     63 
     64 int fs4412_key_fasync(int fd,struct file *filp,int on)
     65 {
     66     fasync_helper(fd,filp,on,&fa);//为了kill_fasync函数做一些成员赋值
     67     return 0;
     68 }
     69 
     70 struct file_operations fops = {
     71     .owner = THIS_MODULE,
     72     .open = fs4412_key_open,
     73     .read = fs4412_key_read,
     74     .fasync = fs4412_key_fasync,
     75 };
     76 
     77 int fs4412_key_probe(struct platform_device *pdev)
     78 {
     79     int ret;
     80     printk("match ok
    ");
     81 
     82     major = register_chrdev(0,"key",&fops);
     83     cls = class_create(THIS_MODULE,"key");
     84     devs = device_create(cls,NULL,MKDEV(major,0),NULL,"key");
     85     
     86     res_key2 = platform_get_resource(pdev,IORESOURCE_IRQ,0);//索引interrupts = <>,<>第一个<>
     87     res_key3 = platform_get_resource(pdev,IORESOURCE_IRQ,1);
     88     ret = request_irq(res_key2->start,fs4412_key_handler,IRQF_TRIGGER_FALLING,"key2",NULL);
     89     ret = request_irq(res_key3->start,fs4412_key_handler,IRQF_TRIGGER_FALLING,"key3",NULL);
     90 
     91     init_waitqueue_head(&keyq);
     92 
     93     init_timer(&t);
     94     t.function = fs4412_key_timer_handler;//定时器中断处理函数
     95     add_timer(&t);//让内核认识定时器中断处理函数
     96     return 0;
     97 }
     98 
     99 int fs4412_key_remove(struct platform_device *pdev)
    100 {
    101     del_timer(&t);
    102     free_irq(res_key3->start,NULL);
    103     free_irq(res_key2->start,NULL);
    104     device_destroy(cls,MKDEV(major,0));
    105     class_destroy(cls);
    106     unregister_chrdev(major,"key");
    107     return 0;
    108 }
    109 
    110 struct of_device_id fs4412_dt_tbl[] = {
    111     {
    112         .compatible = "fs4412,key",
    113     },
    114     {
    115      
    116        },
    117 };
    118 
    119 
    120 struct platform_driver pdrv = {
    121     .driver = {
    122         .name = "fs4412-key",
    123         .of_match_table = fs4412_dt_tbl,
    124     },
    125     .probe = fs4412_key_probe,
    126     .remove = fs4412_key_remove,
    127 };
    128 
    129 module_platform_driver(pdrv);
    130 MODULE_LICENSE("GPL");
    131     
    signal_key.c代码
     1 #include <stdio.h>
     2 #include <sys/types.h>
     3 #include <sys/stat.h>
     4 #include <fcntl.h>
     5 #include <signal.h>
     6 
     7 int fd;
     8 int key;
     9 void func(int signo)
    10 {
    11     if(signo == SIGIO)
    12     {
    13         read(fd,&key,sizeof(key));
    14         printf("key = %d
    ",key);
    15     }
    16 }
    17 
    18 int main(int argc, const char *argv[])
    19 {
    20     signal(SIGIO,func);
    21 
    22     fd = open("/dev/key",O_RDWR);
    23     if(fd == -1)
    24     {
    25         perror("open");
    26         return -1;
    27     }
    28     
    29     int flag;
    30     flag = fcntl(fd,F_GETFL);
    31     flag |= FASYNC;
    32     fcntl(fd,F_SETFL,flag);//主要功能为了调用驱动中的fasync接口
    33     fcntl(fd,F_SETOWN,getpid());
    34     
    35     while(1)
    36     {
    37         printf("hello
    ");
    38         sleep(1);
    39     }
    40     return 0;
    41 }
    应用层代码

    总结:

     1 中断上半部和下半部
     2 将一个中断处理函数分成了2个函数。
     3 
     4 上半部用来处理紧急事件
     5 
     6 紧急事件:
     7 1、直接操作硬件
     8 2、对时间敏感
     9 3、不能被打断的
    10 
    11 下半部:
    12 软中断:
    13     open_softirq();
    14     raise_softirq();
    15 几乎不会使用软中断,内核提供的软中断号都已经被占用了,对应的接口也没有导出符号表。
    16 
    17 小任务:属于一种特殊的软中断,运行在中断上下文,中断处理函数中不能有延时,只能自旋锁。
    18     tasklet_init();//初始化小任务
    19     tasklet_schedule();//调度小任务
    20     
    21 工作队列:运行在进程上下文,可以有延时,可以使用互斥锁,信号量,等待队列。
    22     INIT_WORK();
    23     schedule_work();
    24     
    25 什么时候调度中断下半部?
    26 一般都是在上半部中断处理函数返回前或者返回后。
    27 
    28 多路复用:
    29 int select(文件描述符最大值+1,读表,写表,异常表,超时);
    30 功能:如果文件描述符没有就绪则阻塞。
    31      如果文件描述符就绪则唤醒,唤醒后会清除未就绪的文件描述符。
    32 
    33 vi arch/arm/include/uapi/asm/unistd.h
    34 
    35 
    36 异步通知:当一种事件(按键按下)发生时会在应用层产生一个SIGIO信号,进而捕捉SIGIO信号
    37 
    38 应用层:
    39 
    40 signal(SIGIO,func);
    41 fd = open();
    42 
    43 flag = fcntl(fd,F_GETFL);//从file结构体的f_flags成员中获取属性存放给flag
    44 flag |= FASYNC;
    45 fcntl(fd,F_SETFL,flag);//会和FASYNC进行&,如果成功则会执行驱动中的fasync接口。
    46 fcntl(fd,F_SETOWN,getpid());//明确给哪个进程注册SIGIO信号(还没有真正注册)。
    47 
    48 while(1)
    49 {
    50     功能;
    51 }
    52 
    53 驱动层:
    54 中断处理函数
    55 {
    56     kill_fasync();
    57     //给进程注册信号,但是注册信号时需要使用到一下变量内容,需要准备这些内容
    58 }
    59 
    60 fasync()
    61 {
    62     fasync_helper();//为kill_fasync的功能实现做准备。
    63 }
  • 相关阅读:
    分享我的2014年3月unity3d面试题与参考答案(转)
    Unity3D 面试ABC
    MiniJson解释Json字符串
    Unity3D研究之支持中文与本地文件的读取写入(转)
    unity3d--NGUI制作中文字体
    吊炸天之十步完全理解SQL
    mysql主从同步碰到的问题
    Redis 安装碰到问题
    在Centos系统下使用命令安装gnome图形界面程序
    centos7 网络问题
  • 原文地址:https://www.cnblogs.com/hslixiqian/p/9670835.html
Copyright © 2011-2022 走看看