linux的同步和异步

1.同步

      笔者在本文只分析poll同步机制,首先看poll函数的用法:

       #include
       int poll(struct pollfd fds[], nfds_t nfds, int timeout);

      struct pollfd {
      int fd; /*文件描述符*/
      short events; /* 需要测试的事件 */
      short revents; /* 实际发生的事件,也就是返回结果 */
       };

功能:

查询数组fds中的fd是否发生了events事件,若发生了events事件,poll立即返回,不阻塞;若没有fd发生events事件,则poll阻塞,经过timeout时间后被唤醒。

参数:

nfds指示fds数组的项数,timeout指示poll函数的超时时间(超过时间,则调用poll函数的进程被唤醒),timeout=0,进程不阻塞;timeout<0,进程阻塞到事件发生为止。例子如下:
        ret = poll(fds, 1, 5000);
        if (ret == 0)  //fds中没有可读写的设备文件
        {
            do something;
        }
        else             //fds中有可读写的设备文件
        {
            do otherthing;
        }

返回值:

>0,发生了指定events的fd的数量;=0,没有fd发生了events;-1,调用poll失败

原理:

poll函数最终会调用每个fd对应的xxx_poll函数(属于驱动程序),xxx_poll调用poll_wait()将进程挂到等待队列(不会阻塞),xxx_poll()函数返回一个mask给poll(),该mask里面包含了特定的events,xxx_poll()决定哪种情况下使得mask里面含有POLLIN、POLLRDNORM等events 。poll()函数调用schedule_timeout()进行休眠。例子如下:

static unsigned xxx_poll(struct file *file, poll_table *wait)
{
    unsigned int mask = 0;
    poll_wait(file, &button_waitq, wait); // 不休眠

    if (condition)
        mask |= POLLIN | POLLRDNORM;//条件成立,则设备文件可读,返回表示可读的mask

    return mask;
}

2.异步

原理:
          由文件(驱动程序)向应用程序发送信号,应用程序再调用信号函数。

应用层:

         首先需要应用程序绑定一个信号函数,当收到某个信号后,执行该函数;然后需要将该进程和某个设备文件绑定,这样设备文件可读写时,才知道给那个进程发信号。例子如下:
    signal(SIGIO, my_signal);.//绑定信号函数

    fcntl(fd, F_SETOWN, getpid());//绑定进程和设备文件
    
    Oflags = fcntl(fd, F_GETFL); 
    
    fcntl(fd, F_SETFL, Oflags | FASYNC);//给设备文件添加异步通知标识(调用驱动程序里的xxx_fasync()函数)
   
          三个步骤执行后,设备文件就可以向进程发送信号了。

驱动层:

        在设备驱动程序里,实现向进程发送信号的功能。
         xxx_fasync(),调用fasync_helper()函数,初始化一个结构体
         kill_fasync(),向进程发送信号。

        static int  xxx_fasync (int fd, struct file *filp, int on)
       {
            return fasync_helper (fd, filp, on, &button_async);//初始化fasync_struct结构体,该结构体在向进程发送信号时用到
        }

         kill_fasync (&button_async, SIGIO, POLL_IN);  //设备文件可读写时,调用该函数,向进程发送信号

3.总结

我们在读写设备文件时,可以采用同步或异步机制,同步机制下,需要我们的应用程序自己不断去查询设备文件是否可读写,属于主动出击;而采用异步机制时,应用程序是被动接受信号,当设备文件可读写时,由设备驱动程序给应用程序发信号,应用程序然后才去读写设备文件,属于被动接受。

同步和异步实现,都是靠对应的设备驱动程序。 

你可能感兴趣的:(嵌入式linux)