您的位置 首页 方案

Linux内核开发之异步告诉与异步I/O(二)

“曾经有一份真挚的爱情摆在面前,我却不懂珍惜;曾经有一个承诺,我却倍感珍惜,今天一定要好好讲讲..”讲讲啥,讲讲上节说的那个异步通知的例子呗,大家喜欢看代码,咋们就先上代码:structg

  “曾经有一份真诚的爱情摆在面前,我却不理解爱惜;曾经有一个许诺,我却倍感爱惜,今日一定要好好讲讲..”

  讲讲啥,讲讲上节说的那个异步告诉的比如呗,我们喜爱看代码,咋们就先上代码:

  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/globalfifo

  receive a signal from globalfifo ,signalnum:29

  echo 0>/dev/globalfifo

  receive a signal from globalfifo ,signalnum:29

  echo 0>/dev/globalfifo

  receive a signal from globalfifo ,signalnum:29

  经过上边实践的比如,小王,理解了吧,我的许诺也实现了,下次我们可要开端更高档的东西了..

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/fangan/241514.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部