久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

深入淺出:Linux設(shè)備驅(qū)動中的阻塞和非阻塞I/O

 gljin_cn 2015-04-30
原文出處: 時光漫步LH   歡迎分享原創(chuàng)到伯樂頭條

今天寫的是Linux設(shè)備驅(qū)動中的阻塞和非阻塞I/0,何謂阻塞與非阻塞I/O,?簡單來說就是對I/O操作的兩種不同的方式,驅(qū)動程序可以靈活的支持用戶空間對設(shè)備的這兩種訪問方式,。

一,、基本概念:

  • 阻塞操作 : 是指在執(zhí)行設(shè)備操作時,若不能獲得資源,,則掛起進(jìn)程直到滿足操作條件后再進(jìn)行操作,。被掛起的進(jìn)程進(jìn)入休眠, 被從調(diào)度器移走,,直到條件滿足,。
  • 非阻塞操作 :在不能進(jìn)行設(shè)備操作時,并不掛起,,它或者放棄,,或者不停地查詢,直到可以進(jìn)行操作,。非阻塞應(yīng)用程序通常使用select系統(tǒng)調(diào)用查詢是否可以對設(shè)備進(jìn)行無阻塞的訪問最終會引發(fā)設(shè)備驅(qū)動中 poll函數(shù)執(zhí)行,。

二、輪詢操作

阻塞的讀取一個字符:

1
2
3
4
5
6
7
8
char buf;
fd = open("/dev/ttyS1",O_RDWR);
.....
res = read(fd,&buf,1); //當(dāng)串口上有輸入時才返回,沒有輸入則進(jìn)程掛起睡眠
if(res == 1)
{
 printf("%c/n",buf);
}

非阻塞的讀一個字符:

1
2
3
4
5
char buf;
fd = open("/dev/ttyS1",O_RDWR|O_NONBLOCK);//O_NONBLOCK 非阻塞標(biāo)識
.....
while(read(fd,&buf,1)!=1);//串口上沒有輸入則返回,,所以循環(huán)讀取
printf("%c/n",buf);

阻塞操作常常用等待隊列來實現(xiàn),,而非阻塞操作用輪詢的方式來實現(xiàn)。非阻塞I/O的操作在應(yīng)用層通常會用到select()和poll()系統(tǒng)調(diào)用查詢是否可對設(shè)備進(jìn)行無阻塞訪問,。select()和poll()系統(tǒng)調(diào)用最終會引發(fā)設(shè)備驅(qū)動中的poll()函數(shù)被調(diào)用,。這里對隊列就不多介紹了,大家可以看看數(shù)據(jù)結(jié)構(gòu)里面的知識點,。

應(yīng)用層的select()原型為:

1
2
3
int select(int numfds,fd_set *readfds,fd_set *writefds,fd_set *exceptionfds,
struct timeval *timeout); numfds 的值為需要檢查的號碼最高的文件描述符加1,,若select()在等待timeout時間后,若沒有文件描述符準(zhǔn)備好則返回,。

應(yīng)用程序為:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#inlcude------
main()
{
 int fd,num;
 char rd_ch[BUFFER_LEN];
 fd_set rfds,wfds; //讀寫文件描述符集
 //以非阻塞方式打開/dev/globalfifo設(shè)備文件
 fd=open("/dev/globalfifo",O_RDWR|O_NONBLOCK);
 if(fd != -1)
 {
 //FIFO 清零
 if(ioctl(fd,FIFO_CLEAR,0) < 0)
 {
 printf("ioctl cmd failed /n");
 }
 while(1)
 {
 FD_ZERO(&rfds);
 FD_ZERO(&wfds);
 FD_SET(fd,&rfds);
 FD_SET(fd,&wfds);
 select(fd+1,&rfds,&wfds,null,null);
 }
 }
}

下面說說設(shè)備驅(qū)動中的poll()函數(shù),,函數(shù)原型如下:

1
static unsigned int poll(struct file *file, struct socket *sock,poll_table *wait) //第一個參數(shù)是file結(jié)構(gòu)體指針,,第三個參數(shù)是輪詢表指針,這個函數(shù)應(yīng)該進(jìn)行兩項工作
  • 對可能引起設(shè)備文件狀態(tài)變化的等待隊列調(diào)用poll_wait()函數(shù),,將對應(yīng)的等待隊列頭添加到poll_table
  • 返回表示是否能對設(shè)備進(jìn)行無阻塞讀,,寫訪問的掩碼

這里還要提到poll_wait()函數(shù),很多人會以為是和wait_event()一樣的函數(shù),,會阻塞的等待某件事情的發(fā)生,,其實這個函數(shù)并不會引起阻塞,它的工作是把當(dāng)前的進(jìn)程增添到wait參數(shù)指定的等待列表poll_table中去,,poll_wait()函數(shù)原型如下:

1
2
static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
從中可以看出是將等待隊列頭wait_address添加到p所指向的結(jié)構(gòu)體中(poll_table)

驅(qū)動函數(shù)中的poll()函數(shù)典型模板如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static unsigned int xxx_poll(struct file *filp,struct socket *sock,
 poll_table *wait)
{
unsigned int mask = 0;
struct xxx_dev *dev = filp->private_data;//獲得設(shè)備結(jié)構(gòu)體指針
...
poll_wait(filp,&dev->r_wait,wait);//加讀等待隊列頭到poll_table
poll_wait(filp,&dev->w_wait,wait);//加寫等待隊列頭到poll_table
...
if(...)//可讀
mask |= POLLIN | POLLRDNORM;
if(...)//可寫
mask |= POLLOUT | POLLRDNORM;
...
return mask;
}

三,、支持輪詢操作的globalfifo驅(qū)動

在globalfifo的poll()函數(shù)中,首先將設(shè)備結(jié)構(gòu)體重的r_wait和w_wait等待隊列頭加到等待隊列表,,globalfifo設(shè)備驅(qū)動的poll()函數(shù)如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
static unsigned int gloablfif0_poll(struct file *filp,poll_table *wait)
{
 unsigned int mask = 0;
 struct globalfifo_dev *dev = filp->private_data;
 down(&dev->sem);
 poll_wait(filp,&dev->r_wait , wait) ;
 poll_wait(filp,&dev->r_wait , wait) ;
 if(dev->current_len != 0)
 {
 mask |= POLLIN | POLLRDNORM;
 }
 if(dev->current_len != GLOBALFIFO_SIZE)
 {
 mask |= POLLOUT | POLLWRNORM;
 }
 up(&dev->sem);
 return mask;
}

四,、總結(jié)

阻塞與非阻塞操作:

  • 定義并初始化等待對列頭;
  • 定義并初始化等待隊列,;
  • 把等待隊列添加到等待隊列頭
  • 設(shè)置進(jìn)程狀態(tài)(TASK_INTERRUPTIBLE(可以被信號打斷)和TASK_UNINTERRUPTIBLE(不能被信號打斷))
  • 調(diào)用其它進(jìn)程

poll機制:

  • 把等待隊列頭加到poll_table
  • 返回表示是否能對設(shè)備進(jìn)行無阻塞讀,,寫訪問的掩碼

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多