第8章、linux设备驱动中的阻塞与非io_第1页
第8章、linux设备驱动中的阻塞与非io_第2页
第8章、linux设备驱动中的阻塞与非io_第3页
第8章、linux设备驱动中的阻塞与非io_第4页
第8章、linux设备驱动中的阻塞与非io_第5页
已阅读5页,还剩16页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 !#$%&()*+,-. !#$%&()*+,-.第 8 章Linux 设备驱动中的阻塞与非阻塞 I/O阻塞和非阻塞 I/O 是设备的两种不同模式,驱动程序可以灵活地支持用户空间对设备的这两种方式。节讲解阻塞 I/O 和非阻塞 I/O 的区别,实现阻塞 I/O 的等待队列机制,以及在globalfifo 设备驱动中增加对阻塞 I/O 支持的方法,并进行了用户空间的验证。节讲解设备驱动的轮询(poll)操作的概念和编程方法,poll 操作可以帮助用户了解是否能对设备进行无阻塞。8.3 节讲解在 globalfifo 中增加 poll 操作的方法,并进行了用户空间的验证。=wxB!io01wx#

2、$G%&()*+nKJ,-./Mwx0123nowx4*+nKn!5678J49:;?J,-bcwxnGno01wx#mG*+JABCDEJBCGFQGtJ,HMNnowxIJ23KLKLMNOPYQR.STTKLno read()Uwrite()bVW:T#J$01Z01J23KLTi0123,-(MN%XJ2JTTKL read()Uwrite()b:T_JabcKdenopfgZ01m1J)S01(GM%X#J01239rstu+vwxyz|J)GeJ 0123G=J)TU!%X01(GFQGtJY#$ %Q& CPU (=G%X(nK$n!5678J,J-.g/i0bQZ12356n

3、K23nKQZ45M56i;78sJ,I91(%&H#:;q0b;7=8.1 AA=ZCD0brE=FIJHMIJKusigactionvNLMZCDNON CPU OTJY8PPBIpQR=?=?= I/O8.1.1bcdei Linux 23KL;JMNGTbcdeuwait queuevva=nK23wait queue STUxI0bVWXZai Linux 8pJANdeIV_aJ?nK:;fgbcdJ1Tea;LMf1KkfgbcdeMNTvHMXVW(cdevaJ9 7 :;ghJKii;pjkbLinux 2.6 OP+lebcdewx10123456789:20;=34567

4、89:+s DECLARE_WAIT_QUEUE_HEAD()mMNxInompqrbcdestuvZw30124567:xmTenompqr0byI name ?/A4567:add_wait_queue()Tebcde wait zk-bcdes q !bcde|;J remove_wait_queue()Tebcde wait 9bcdes q ! 5045BC:bc90b! queue xIbcdeswait_event()A wait_event_erruptible()_ie2 CMN4JK$7J%CGkt_timeout 2bc/*789:;?ABCDE*/ while(0)#d

5、efinedo wait_event(wq,condition)DEFINE_WAIT( wait); ERRUPTIBLE);for (;) prepare_to_wait(&wq, if (condition)break;& wait,TASK_UNschedule();/*FG CPU*/finish_wait(&wq, & wait); while (0)void fastcall22 prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait,se)232425262728293031323334unsigned long fla

6、gs;wait-flags &= WQ_FLAG_EXCLUSIVE; spin_lock_irqsave(&q-lock, flags); if (list_empty(&wait-task_list) add_wait_queue(q, wait);/=?ABif (is_sync_wait(wait)set_current_se(se);/HI JKLMNOPQRspin_unlock_irqrestore(&q-lock, flags);35 void fastcall finish_wait(wait_queue_head_t *q, wait_queue_t *wait) 36 3

7、7 unsigned long flags;60FG67:thwx$23N queue xIbcdesgibcde;giexbcdesbcdeXTnKwake_up() T ? wait_event() Bwait_event_timeout() , X G TJ Bewake_up_erruptible()T, X?Gwait_event_erruptible() wake_up() M 2 3wait_event_erruptible_timeout()T-JTASK_ERRUPTIBLEATASK_UNERRUPTIBLE n Kwake_up_erruptible()23-e TASK

8、_ERRUPTIBLE nK70H4567IJK:sleep_on().xTUB/%nK780, TASK_UNERRUPTIBLEJmno0bbcdeJ122A-bcdes qJ,-(M%&Jq 34b cde423erruptible_sleep_on()? sleep_on().5wJ*xTB/%nK780,TASK_ERRUPTIBLEJmno0bbcdeJ122A-bcdes qJ,-(M%&Jq 34bcde423BCnK6-JKsleep_on() . T x ? wake_up() , X G TJerruptible_sleep_on() T x ?wake_up_errup

9、tible(),XGT=8.4 A=(task_list) spin_lock_irqsave(&q-lock, flags);list_del_init(&wait-task_list);spin_unlock_irqrestore(&q-lock, flags); 44 45 8.4sleep_on()DE ! !8.5erruptible_sleep_on()DE9 = 8.4 A Zbcdesi;GTset_current_se().B_ _add_wait_queue().va/%nK789:J,;se = TASK_UNERRUPTIBLE 5w?pBMoKLAJset_curre

10、nt_se().iBCDE+8MNGTJG$Fim 5DGJHBN|e_ _add_ wait_queue(),JiIJ0123;JmG:T sleep_on()Berruptible_sleep_on()JBKLnonK789:AMNJse = TASK_ERRUPTIBLE;/HI JKLNO 6SLEEP_ON_HEADschedule();/FG CPUSLEEP_ON_TAIL10 1 void fastcall _ _schederruptible_sleep_on(wait_queue_head_t *q) 2 SLEEP_ON_VAR/* #define SLEEP_ON_VA

11、Runsigned long flags;wait_queue_t wait;init_waitqueue_entry(&wait, current); */current-se = TASK_UNERRUPTIBLE;/HI JKLNO 9SLEEP_ON_HEAD/* #define SLEEP_ON_HEADspin_lock_irqsave(&q-lock,flags);_ _add_wait_queue(q, &wait);spin_unlock(&q-lock);*/ 15schedule();/FG CPUSLEEP_ON_TAIL/* #define SLEEP_ON_TAIL

12、spin_lock_irq(&q-lock);_ _remove_wait_queue(q, &wait);spin_unlock_irqrestore(&q-lock, flags); */ 22 !8.6 HLMNOPQRSNTUVWX schedule()ic ssize_t_write(struct file *file, const char *buffer,1 ssize_t234567891011121314151617181920212223242526272829303132333435363738count, loff_t *p.)DECLARE_WAITQUEUE(wai

13、t, current); /UV?AB_ _add_wait_queue(&_wait, &wait); /=?ABret = count;/* ?WXYZ */ doavail = device_writable(.); if (avail 0)_ _set_current_se(TASK_ERRUPTIBLE);/HIKLNOif (avail f_flags &O_NONBLOCK) /DEif (!ret)ret = - EAGAIN;goto out;schedule(); /_abKLcdif (signal_pending(current)/efghPijklif (!ret)r

14、et = - ERESTARTSYS;goto out;while (avail wx globalfifo 0123) globalfifo jkYQQR.2 globalfifo ;STF:,0b FIFOJiS FIFO ;i_#UuoinK2_V-Yb FIFO hi4BnKB VvJBnK2_BZJ2_$9 globalfifo STF;4WXl iS FIFO .#uoHi0YVWZ4VJBV.24BnK9Yb FIFO ;BZp_vJVnK:Yb FIFO ;V!_aiJ globalfifo yItglobalfifowJi globalfifo ;JB FIFO 23V FI

15、FOJV FIFO p23B FIFOJMN_901aJi*;jkEbbcdeAVJ=8.7 gAsJ?_XT !8.7 globalfifo YZ? globalfifo01aa0bGHBjkp current_len ,bTec/%FIFO ;i_d;YbbcdeMi0123Iekf.;:T init_waitqueue_head()4pqrJg0123Iekf.w_wait423r_waitJprivate_data; /+,WXrs t-.DECLARE_WAITQUEUE(wait, current); /124567813 if (ret sem); /*()ij!*/init_w

16、aitqueue_head(&globalfifo_devp-r_wait); /*;w_wait); /*;sem); /+,ij!add_wait_queue(&dev-r_wait, &wait); /Se45678/* ? FIFO / */(dev-current_len = 0)ifif (filp-f_flags &O_NONBLOCK)ret = - EAGAIN;goto out;_ _set_current_se(TASK_ERRUPTIBLE);/HIKLNOP0R21222324252627282930313233343536373839404142434445up(&

17、dev-sem);schedule(); /_abKLcd if (signal_pending(current)/efghPijklret = - ERESTARTSYS;goto out2;down(&dev-sem);/*if1 2/3 */(count dev-current_len)count = dev-current_len;(copy_to_user(buf, dev-mem,ifcount)ret = - EFAULT;goto out;elsememcpy(dev-mem, dev-mem + count, dev-current_len - count);/fifo vw

18、Jn46dev-current_len -= count; /$uvwx45prk(KERN_INFO read %d bytes(s),current_len:%dn, count,47dev-current_len);48495051525354558A56575859606162wake_up_erruptible(&dev-w_wait); /FG_4567ret = count;out: up(&dev-sem); /ij!out2: remove_wait_queue(&dev-w_wait, &wait); /fgh4567set_current_s return ret;e(T

19、ASK_RUNNING);/*globalfifo 78*/ic ssize_t globalfifo_write(struct file *filp, const char_s_user *buf,size_tcount, loff_t *p636465t-.66676869707172737475767778798081K8283848586878889909192939495)globalfifo_dev *dev = filp-private_data; /+,WXrsstructret;DECLARE_WAITQUEUE(wait, current); /124567down(&de

20、v-sem); /+6ij!add_wait_queue(&dev-w_wait, &wait); /Se_45678/* ? FIFO 9 */(dev-current_len = GLOBALFIFO_SIZE)ifif (filp-f_flags &O_NONBLOCK)/efgDEret = - EAGAIN;goto out;_ _set_current_se(TASK_ERRUPTIBLE);/QRSNTUiJup(&dev-sem);schedule(); /WjklSNmn if (signal pending(current)/opqristFGret = - ERESTAR

21、TSYS;goto out2;down(&dev-sem); /+,ij!/*; 2/31/3*/=8.9 -hpbcdenZAnKMNcurrent_len != 0 r_wait,dev-current_len != 0 vkNJ 2V. ; 05 i Tebc dev-current_len !=GLOBALFIFO_SIZE w_wait,dev-current_len != 0vkNlmFt JU ng bc de V A . r_wait, dev- current_len != 0 v A9 13 p 32 o=w_wait, dev- current_len != 0vA9 7

22、3p93 o=XqS0Qrs_ai9 13p32 o=A9 73p93 osemvJ)uvGMwxy 8.1uavgAJz0/%current_len I 0J# i 0 b B nKJ A $ %& JKi J , I01 G ./ J A , I wait_event_ erruptible(dev-r_wait, dev- current_len != 0) =J dev-r_wait bcdeh( dev-current_len != 0 wxYMNiVnK;noJVnpJKiY0rs3xyoJoVwx%Y-.bcBnKsJ9uvJKiJ,|bcXZ(Ty 8.1ubvgAJz0/%c

23、urrent_len IGLOBALFIFO_SIZEJ # i 0 b V nKJ A % & J K i J , I01 G ./ J A , Iwait_event_erruptiblue dev-w_wait, dev-current_len != GLOBALFIFO_SIZEv=Jif (count GLOBALFIFO_SIZE - dev-current_len)count = GLOBALFIFO_SIZE - dev-current_len; 9899if (copy_from_user(dev-mem + dev-current_len, buf, count)100re

24、t = - EFAULT;goto out;103104else105dev-current_len += count;prk(KERN_INFO written %d bytes(s),current_len:%dn, count, dev-current_len);wake_up_erruptible(&dev-r_wait); /FG4567ret = count;113114out: up(&dev-sem); /ij!out2: remove_wait_queue(&dev-w_wait, &wait); /;=M?AB pn?set_current_se(TASK_RUNNING)

25、;return ret;119 而dev-w_wait 等待队列及让dev-current_ len != GLOBALFIFO_SIZE 的操作又需要在读进程中进行,读进执行读操作前又必须等待写进程信号量,造成互相等待对方资源的局面,从而死锁。所谓死锁,就是多个进程循环等待它方占有的资源而无限期地僵持下去的局面。如果没有外力的作用,那么死锁涉及的各个进程都将处于状态。因此,驱动工程师一定要注意:当多个等待队列、信号量等机制同时出现时,谨防死锁。现在回过来看一下代码8.9 的第 15 行和第 75 行,发现在设备驱动的 read()、write()等功能函数中,可以通过 filp-f_flag

26、s 标志获得用户空间是否要求非阻塞。驱动中可以依据此标志判断用户究竟要求阻塞还是非阻塞理。,从而进行不同的处S echo nK/dev/globalfifo V!0C_Jcat nKUnoxC_?aZv8.2.1st?=l I/O select()A poll()VW:T4A$0123; poll().4oJi 2.5.45 ;H3!p epoll()JoBC poll()select()A poll()VW:TWD0QJ%Ci BSD UNIX ;3!J2Ci System V;3!stwxrootlocalhost root# a great ChiLinux driver Enginee

27、r8.2.2TTKL;stKTTKL;4EFT-B BSD UNIX ;3! select()VW:TJ*GH+.*; readfdsUwritefdsUexceptfds ?_B4 select()IJBUVALL-hm 1KhELdJnumfds BMNMGK=4Nm1KhEk 1timeout !B0b! struct timeval 5H!NJAMNG select()ibc timeout #W2$him1KhEO1P)_struct timeval _ano=8.10 gA !8.10 timeval 12+ewxTv00U U57m1KhELd 0bm1KhEL0bm1KhEk!

28、m1KhEL;0bm1KhE9m1KhEL; 57m1KhEB40Y8.2.30123;stK0123; poll().GH+.90b!I file a!NJ9#b!Ist!NYb.TxnoN+EQ-xXM3+01m178:rbcde:T poll_wait().JXTBUVR=lSTe poll_tablebcde poll_wait().GH+.poll_wait().QbcZf1poll_wait().g- xB2S%nKzk- wait !nbceupoll_tablev;23KL poll().Tx_01(M%X78Jo POLLINUPOLLOUTUPOLLPRIUPOLLERRU

29、POLLNVAL bmbmo8R01void poll_wait(struct file *filp, wait_queue_heat_t *queue, poll_table* wait);unsigned(*poll)(struct file * filp, struct poll_table* wait);FD_ISSET(fd,fd_set *set)FD_CLR(fd,fd_set *set)FD_SET(fd,fd_set *set)FD_ZERO(fd_set *set)struct timevaltv_sec; /* */ tv_usec; /* AB */;select(nu

30、mfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,struct timeval *timeout);QBJPOLLOUTunoI 0 x0004vyz01MN =QVKcNt?JZ0123; poll().HI_J=8.11 gA !8.11poll()DEuvw8.3.1i globalfifo 23;jkstwxi globalfifo poll().;J01a;current_len Bbe 0 v%&01current_len Bbe GLOBALFIFO_SIZE v%&01MV78J=8.12 gA !8.12 g

31、lobalfifo YZLM poll()DE1 sic unsignedglobalfifo_poll(struct file *filp, poll_table*wait)2 3unsignedmask = 0;RSstwxprivate_data; /*+,WXrst-.*/ 56.poll_wait(filp, &dev-r_wait, wait);/5?ABppoll_wait(filp, &dev-w_wait, wait);/?ABp 910if (.)/51112mask |= POLLIN | POLLRDNORM; /*CDvw+,*/ 131415if (.)/1617m

32、ask |= POLLOUT | POLLWRNORM; /*CDvw&*/ 181920.21return mask; 22 /yN2 globalfifo_poll =) globalfifo_fops poll ,bJ+gA.8.3.2iTUVWqr globalfifo 01stV0bTTKL pollmonitor.c Te8.13 gAglobalfifo MBV78JYbKLprivate_data; /*+,WXrs t-.*/56down(&dev-sem); 7poll_wait(filp, &dev-r_wait, wait);poll_wait(filp, &dev-w

33、_wait, wait);10/*fifo /*/11if (dev-current_len != 0) 1213mask |= POLLIN | POLLRDNORM; /*CDvw+,*/ 1415/*fifo 9*/16if (dev-current_len != GLOBALFIFO_SIZE) 1718mask |= POLLOUT | POLLWRNORM; /*CDvw&*/ 1920up(&dev-sem);return mask; 23 =o#+-JShiBC!Jo FIFO IV#JKLG7QZtPoll monitor:canbe writtenwlSKc echo /dev/globalfifo V!0Y_2JZtPoll monitor:can be readwAtPoll monitor:can be writtenwl G7QKc echo /dev/globalfifo Vchar rd_chB

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论