高级字符设备驱动-阻塞型字符设备驱动笔记

 

问题:

当一个设备无法立即满足用户的读写请求时应当如何处理?

例如:调用read时没有数据可读,但以后会有。调用write时没空间可以写,但设备暂时没有准备好接收数据

这时候,驱动程序应当阻塞进程,使它进入睡眠,直到请求可以得到满足。

 

解决:

阻塞方式是文件读写操作的默认方式,但应用程序员可以通过使用O_NONBLOCK标志来人为的设置读写操作为非阻塞方式(在<linux/fcntl.h>中,在打开文件中指定

非阻塞方式时,调用readwrite,遇到上述问题,系统只是简单地返回-EAGAIN,而不会再阻塞进程。

代码:

/*mem设备描述结构体*/

struct mem_dev                                     

{                                                        

  char *data;                      

  unsigned long size; 

  wait_queue_head_t inq;     //定义了等待队列  

};

  

/*设备驱动模块加载函数  节选*/

static int memdev_init(void)

{

 /*为设备分配内存*/

  for (i=0; i < MEMDEV_NR_DEVS; i++) 

  {

        mem_devp[i].size = MEMDEV_SIZE;

        mem_devp[i].data = kmalloc(MEMDEV_SIZE, GFP_KERNEL);

        memset(mem_devp[i].data, 0, MEMDEV_SIZE);

  

   /*初始化等待队列*/

  init_waitqueue_head(&(mem_devp[i].inq));

  }

 }

while (!have_data) /* 没有数据可读,考虑为什么不用if,而用while,中断信号唤醒 */

{

        if (filp->f_flags & O_NONBLOCK)

            return -EAGAIN;

wait_event_interruptible(dev->inq,have_data);  //把调用驱动程序的应用程序阻塞在inq的等待队列中

}

/*写函数*/

static ssize_t mem_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)

{

 

  have_data = true; /* 有新的数据可读 */

    

    /* 唤醒读进程 */

wake_up(&(dev->inq));

}


测试程序:

先读,让进程阻塞,再写,让进程唤醒

#include <stdio.h>

int main()

{

FILE *fp = NULL;

char Buf[128];

/*初始化Buf*/

strcpy(Buf,"memdev is char dev!");

printf("BUF: %s\n",Buf);

/*打开设备文件*/

fp = fopen("/dev/memdev0","r+");

if (fp == NULL)

{

printf("Open memdev0 Error!\n");

return -1;

}

/*清除Buf*/

strcpy(Buf,"Buf is NULL!");

printf("Read BUF1: %s\n",Buf);

/*读出数据*/

fread(Buf, sizeof(Buf), 1, fp);

/*检测结果*/

printf("Read BUF2: %s\n",Buf);

fclose(fp);

return 0; 

}

#include <stdio.h>

int main()

{

FILE *fp = NULL;

char Buf[128];

/*打开设备文件*/

fp = fopen("/dev/memdev0","r+");

if (fp == NULL)

{

printf("Open Dev memdev0 Error!\n");

return -1;

}

/*写入设备*/

strcpy(Buf,"memdev is char dev!");

printf("Write BUF: %s\n",Buf);

fwrite(Buf, sizeof(Buf), 1, fp);

sleep(5);

fclose(fp);

return 0; 

}

你可能感兴趣的:(struct,File,user,测试,null,FP)