Linux核心開發之非同步通知與非同步I/O(二)

來源:互聯網
上載者:User

“曾經有一份真摯的愛情擺在面前,我卻不懂珍惜;曾經有一個承諾,我卻倍感珍惜,今天一定要好好講講..”

講講啥,講講上節說的那個非同步通知的例子唄,大家喜歡看代碼,咋們就先上代碼:

struct globalfifo_dev                                     {                                                          struct cdev cdev; /*cdev結構體*/                         unsigned int current_len;    /*fifo有效資料長度*/  unsigned char mem[GLOBALFIFO_SIZE]; /*全域記憶體*/          struct semaphore sem; /*並發控制用的訊號量*/             wait_queue_head_t r_wait; /*阻塞讀用的等待隊列頭*/       wait_queue_head_t w_wait; /*阻塞寫用的等待隊列頭*/      struct fasync_struct *async_queue; /* 非同步結構體指標,用於讀 */ };/*檔案釋放函數*/int globalfifo_release(struct inode *inode, struct file *filp){/* 將檔案從非同步通知清單中刪除 */  globalmem_fasync( - 1, filp, 0);  return 0;}static int globalfifo_fasync(int fd, struct file *filp, int mode){struct globalfifo_dev *dev = filp->private_data; return fasync_helper(fd, filp, mode, &dev->async_queue);}/*globalfifo寫操作*/static ssize_t globalfifo_write(struct 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); //進入寫等待隊列頭  /* 等待FIFO非滿 */  if (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 "written %d bytes(s),current_len:%d\n", count, dev      ->current_len);    wake_up_interruptible(&dev->r_wait); //喚醒讀等待隊列    /* 產生非同步讀訊號 */    if (dev->async_queue)       kill_fasync(&dev->async_queue, SIGIO, POLL_IN);        ret = count;  }  out: up(&dev->sem); //釋放訊號量  out2:remove_wait_queue(&dev->w_wait, &wait); //從附屬的等待隊列頭移除  set_current_state(TASK_RUNNING);  return ret;}下面再給出測試程式:
#include ...//接收到非同步讀訊號的動作void input_handler(int signum){    printf("Receive a signal from globalfifo,signalnum:%d\n",signum);}int main(){  int fd, oflags;  fd = open("/dev/globalfifo", O_RDWR, S_IRUSR | S_IWUSR);  if (fd !=  - 1)  {       //啟動訊號驅動機制    signal(SIGIO, input_handler); //讓input_handler()處理SIGIO訊號    fcntl(fd, F_SETOWN, getpid());    oflags = fcntl(fd, F_GETFL);    fcntl(fd, F_SETFL, oflags | FASYNC);    while(1)    {    sleep(100);    }  }  else  {    printf("device open failure\n");  }}
當我們載入完驅動並建立完裝置節點後,運行上述程式,每當通過echo向/dev/globalfilfo寫入新的資料後,input_handler將會被調用。如下所示:echo 0>/dev/globalfiforeceive a signal from globalfifo ,signalnum:29 echo 0>/dev/globalfiforeceive a signal from globalfifo ,signalnum:29

 

echo 0>/dev/globalfiforeceive a signal from globalfifo ,signalnum:29

通過上邊實際的例子,小王,明白了吧,我的承諾也兌現了,下次咱們可要開始更進階的東西了..

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.