ºìÁªLinuxÃÅ»§
Linux°ïÖú

Äں˵ȴý¶ÓÁлúÖƽéÉÜ

·¢²¼Ê±¼ä:2006-08-27 09:49:33À´Ô´:ºìÁª×÷Õß:maya_human
¡¡¡¡ÏàÐźܶàд³ÌÐòµÄÈ˶¼Ð´¹ý socket µÄ³ÌÐò¡£µ±ÎÒÃÇ open Ò»¸ö socket Ö®ºó£¬½Ó×ÅÈ¥¶ÁÈ¡Õâ¸ö socket£¬Èç¹û´ËʱûÓÐÈκÎ×ÊÁϿɹ©¶ÁÈ¡£¬ÄÇ read ¾Í»á block ס¡£(ÕâÊÇûÓмÓÉÏ O_NONBLOCK µÄÇéÐÎ)£¬Ö±µ½ÓÐ×ÊÁϿɶÁÈ¡²Å»á´«»ØÀ´¡£ÔÚ Linux kernel ÀïÓÐÒ»¸öÊý¾Ý½á¹¹¿ÉÒÔ°ïÖúÎÒÃÇ×öµ½ÕâÑùµÄ¹¦ÄÜ¡£Õâ¸öÊý¾Ý½á¹¹¾ÍÊÇÕâÀïÒª¸ú¸÷λ½éÉÜµÄ wait queue¡£ÔÚ kernel Àwait_queue µÄÓ¦Óúܹ㣬¾Ù·² device driver semaphore µÈ·½Ã涼»áʹÓõ½ wait_queue À´ implement¡£ËùÒÔ£¬ËüËãÊÇ kernel ÀïÂù»ù±¾µÄÒ»¸öÊý¾Ý½á¹¹¡£
¡¡¡¡
¡¡¡¡½ÓÏÂÀ´£¬ÎÒÒª¸ú¸÷λ½éÉÜһϠwait_queue µÄÓ÷¨£¬ÒÔ¼°ÓÃÒ»¸öÀý×ÓÀ´ËµÃ÷ÈçºÎʹÓà wait_queue¡£×îºó£¬ÎÒ»á´ø¸÷λȥ trace һϠwait_queue µÄԭʼ³ÌÐò´úÂ룬¿´¿´ wait_queue ÊÇÈçºÎ×öµ½µÄ¡£
¡¡¡¡
¡¡¡¡ÎÒÏëÓмþÊÂÒªÏÈÌá¼°µÄÊÇ Linux ÔÚ user space ¸úÔÚ kernel space ÉϵIJîÒì¡£ÎÒÃÇÖªµÀ Linux ÊÇ multi-tasking µÄ»·¾³£¬Í¬Ê±¿ÉÒÔÓкܶàÈËÖ´ÐкܶàµÄ³ÌÐò¡£ÕâÊÇ´Ó user µÄ¹ÛµãÀ´¿´µÄ¡£Èç¹û¾Í kernel µÄ¹ÛµãÀ´¿´£¬ÊÇûÓÐËùνµÄ multi-tasking µÄ¡£ÔÚ kernel ÀֻÓÐ single-thread¡£Ò²¾ÍÊÇ˵£¬Èç¹ûÄãµÄ kernel code ÕýÔÚÖ´ÐУ¬ÄÇϵͳÀïÖ»ÓÐÄDz¿·ÖÔÚÖ´ÐС£²»»áÓÐÁíÒ»²¿·ÖµÄ kernel code Ò²ÔÚÔË×÷¡£µ±È»£¬ÕâÊÇÖ¸ single processor µÄÇé¿öÏ£¬Èç¹ûÊÇ SMP µÄ»°£¬ÄÇÎҾͲ»Çå³þÁË¡£ÎÒÏëºÜ¶àÈ˶¼ÔÚ Windows 3.1 ÏÂд¹ý³ÌÐò£¬ÔÚÄÇÖÖ»·¾³ÏÂд³ÌÐò£¬Ã¿Ò»¸ö³ÌÐò¶¼±ØÐëÊʵ±µÄ½« CPU Èøø±ðµÄ³ÌÐòʹÓá£Èç¹ûÓиö³ÌÐòÀïÃæÓÐÒ»¸ö
¡¡¡¡
[code]¡¡¡¡while (1);[/code]
¡¡¡¡
¡¡¡¡µÄ»°£¬ÄDZ£Ö¤ÏµÍ³¾ÍÍ£ÔÚÄÇÀïÁË¡£ÕâÖֵĶàÈÎÎñ½Ð×ö non-preemptive¡£Ëü¶àÈÎÎñµÄÌØÐÔÊÇÓɸ÷¸ö³ÌÐòÏ໥ºÏ×÷¶øÔì³ÉµÄ¡£ÔÚ Linux µÄ user space Ï£¬ÔòÊÇËùνµÄ preemptive£¬¸÷¸ö process ϲ»¶Ö´ÐÐʲô¾ÍÖ´ÐÐʲô£¬¾ÍËãÄãÔÚÄãµÄ³ÌÐòÀï¼ÓÉÏ while(1); ÕâÒ»ÐÐÒ²²»»áÓ°ÏìϵͳµÄÔË×÷¡£·´Õýʱ¼äµ½ÁË£¬ÏµÍ³×Ô¶¯¾Í»á½«ÄãµÄ³ÌÐòͣס£¬ÈñðµÄ³ÌÐòÈ¥Ö´ÐС£ÕâÊÇÔÚ user space µÄÇé¿öÏ£¬ÔÚ kernel Õâ·½Ã棬¾Í¸ú Windows 3.1 ³ÌÐòÊÇÒ»ÑùµÄ¡£ÔÚ kernel ÀÄã±ØÐëÊʵ±µÄ½« CPU µÄÖ´ÐÐȨÊͷųöÀ´¡£Èç¹ûÄãÔÚ kernelÀï¼ÓÈë while(1); ÕâÒ»ÐС£ÄÇϵͳ¾Í»á¸ú Windows 3.1 Ò»Ñù¡£¿¨ÔÚÄÇÀï¡£µ±È»À²£¬ÎÒÊÇûÊÔ¹ýÕâÑùÈ¥¸Ä kernel£¬ÓÐÐËȤµÄÈË¿ÉÒÔÈ¥ÊÔÊÔ¿´£¬Èç¹ûÓв»Í¬µÄ½á¹û£¬Çë¼ÇµÃ¸æËßÎÒ¡£
¡¡¡¡
¡¡¡¡¼ÙÉèÎÒÃÇÔÚ kernel Àï²úÉúÒ»¸ö buffer£¬user ¿ÉÒÔ¾­ÓÉ read£¬write µÈ system call À´¶ÁÈ¡»òд×ÊÁϵ½Õâ¸ö buffer Àï¡£Èç¹ûÓÐÒ»¸ö user д×ÊÁϵ½ buffer ʱ£¬´Ëʱ buffer ÒѾ­ÂúÁË¡£ÄÇÇëÎÊÄãÒªÈçºÎÈ¥´¦ÀíÕâÖÖÇéÐÎÄØ ? µÚÒ»ÖÖ£¬´«¸ø user Ò»¸ö´íÎóѶϢ£¬Ëµ buffer ÒѾ­ÂúÁË£¬²»ÄÜÔÙдÈë¡£µÚ¶þÖÖ£¬½« user µÄÒªÇó block ס£¬µÈÓÐÈ˽« buffer ÄÚÈݶÁ×ߣ¬Áô³ö¿Õλʱ£¬ÔÙÈà user дÈë×ÊÁÏ¡£µ«ÎÊÌâÀ´ÁË£¬ÄãÒªÔõô½« user µÄÒªÇó block ס¡£ÄѵÀÄãÒªÓÃ
¡¡¡¡
[code]¡¡¡¡while ( is_full );
¡¡¡¡write_to_buffer;[/code]
¡¡¡¡
¡¡¡¡ÕâÑùµÄ³ÌÐò´úÂëÂð? ÏëÏë¿´£¬Èç¹ûÄãÕâÑù×ö»á·¢ÉúʲôÊÂ? µÚÒ»£¬kernel»áÒ»Ö±ÔÚÕâ¸ö while ÀïÖ´ÐС£µÚ¶þ¸ö£¬Èç¹û kernel Ò»Ö±ÔÚÕâ¸ö while ÀïÖ´ÐУ¬±íʾËüûÓа취ȥ maintainϵͳµÄÔË×÷¡£ÄÇ´Ëʱϵͳ¾ÍÏ൱ÓÚµ±µôÁË¡£ÔÚÕâÀï is_full ÊÇÒ»¸ö±äÁ¿£¬µ±È»£¬Äã¿ÉÒÔÈà is_full ÊÇÒ»¸ö function£¬ÔÚÕâ¸ö functionÀï»áÈ¥×ö±ðµÄÊÂÈà kernel ¿ÉÒÔÔË×÷£¬ÄÇϵͳ¾Í²»»áµ±¡£ÕâÊÇÒ»¸ö·½Ê½¡£µ«ÊÇ£¬Èç¹ûÎÒÃÇʹÓà wait_queue µÄ»°£¬ÄdzÌÐò¿´ÆðÀ´»á±È½ÏƯÁÁ£¬¶øÇÒÒ²±È½ÏÈÃÈËÁ˽⣬ÈçÏÂËùʾ:
¡¡¡¡¡¡
[code]¡¡¡¡struct wait_queue *wq = NULL; /* global variable */
¡¡¡¡while ( is_full ) {
¡¡¡¡interruptible_sleep_on( &wq );
¡¡¡¡}
¡¡¡¡write_to_buffer();[/code]
¡¡¡¡
¡¡¡¡interruptible_sleep_on( &wq ) ÊÇÓÃÀ´½«Ä¿Ç°µÄ process£¬Ò²¾ÍÊÇÒªÇóд×ÊÁϵ½ buffer µÄ process·Åµ½ wq Õâ¸ö wait_queue Àï¡£ÔÚ interruptible_sleep_on ÀÔòÊÇ×îºó»áºô½Ð schedule() À´×ö schedule µÄ¶¯×÷£¬Ò²¾ÍÊÇÈ¥ÕÒÁíÒ»¸ö process À´Ö´ÐÐÒÔά³ÖϵͳµÄÔË×÷¡£µ±Ö´ÐÐÍê interruptible_sleep_on Ö®ºó£¬ÒªÇó write µÄ process ¾Í»á±» block ס¡£ÄÇʲôʱºò»á»Ö¸´Ö´ÐÐÄØ ? Õâ¸ö process Ö®ËùÒԻᱻ block סÊÇÒòΪ buffer µÄ¿Õ¼äÂúÁË£¬ÎÞ·¨Ð´Èë¡£µ«ÊÇÈç¹ûÓÐÈ˽« buffer µÄ×ÊÁ϶ÁÈ¡µô£¬Ôò buffer ¾ÍÓпռä¿ÉÒÔÈÃÈËдÈë¡£ËùÒÔ£¬ÓйØÓÚ½ÐÐÑ process µÄ¶¯×÷Ó¦¸ÃÊÇÔÚ read buffer Õâ·½ÃæµÄ³ÌÐò´úÂë×öµÄ¡£
¡¡¡¡
[code]¡¡¡¡extern struct wait_queue *wq;
¡¡¡¡if ( !is_empty ) {
¡¡¡¡read_from_buffer();
¡¡¡¡wake_up_interruptible( &wq );
¡¡¡¡}
¡¡¡¡....[/code]
¡¡¡¡
¡¡¡¡ÒÔÉϵijÌÐò´úÂëÓ¦¸ÃÒª·ÅÔÚ read buffer Õⲿ·ÖµÄ³ÌÐò´úÂëÀµ± buffer ÓжàÓàµÄ¿Õ¼äʱ,ÎÒÃǾͺô½Ð wake_up_interruptible( &wq ) À´½«¹ÒÔÚ wq ÉϵÄËùÓÐ process ½ÐÐÑ¡£Çë¼ÇµÃ£¬ÎÒÊÇ˵½« wq ÉϵÄËùÓÐ process ½ÐÐÑ£¬ËùÒÔ£¬Èç¹ûÈç¹ûÓÐ10¸ö process ¹ÒÔÚ wq ÉϵĻ°£¬ÄÇÕâ 10 ¸ö¶¼»á±»½ÐÐÑ¡£Ö®ºó£¬ÖÁÓÚË­ÏÈÖ´ÐС£ÔòÊÇÒª¿´ schedule ÊÇÔõô×öµÄ¡£¾ÍÊÇÒòΪÕâ 10 ¸ö¶¼»á±»½ÐÐÑ¡£Èç¹û A ÏÈÖ´ÐУ¬¶øÇÒÍòÒ»ºÜ²»´ÕÇɵģ¬A ÓÖ°Ñ buffer дÂúÁË£¬ÄÇÆäËü 9 ¸ö process ÒªÔõô°ìÄØ? ËùÒÔÔÚ write buffer µÄ²¿·Ö£¬ÐèÒªÓÃÒ»¸ö while À´¼ì²é buffer Ä¿Ç°ÊÇ·ñÂúÁË.Èç¹ûÊǵĻ°£¬ÄǾͼÌÐø¹ÒÔÚ wq ÉÏÃæ.
¡¡¡¡
¡¡¡¡ÉÏÃæËù̸µÄ¾ÍÊÇ wait_queue µÄÓ÷¨¡£ºÜ¼òµ¥²»ÊÇÂð? ½ÓÏÂÀ´£¬ÎÒ»áÔÙ½éÉÜһϠwait_queue ÌṩÄÇЩ function ÈÃÎÒÃÇʹÓá£ÈÃÎÒÔÙÖØÉêÒ»´Î¡£wait_queue Ó¦ÉèΪ global variable£¬±È·½½Ð wq£¬Ö»ÒªÈÎºÎµÄ process Ï뽫×Ô¼º¹ÒÔÚÉÏÃ棬¾Í¿ÉÒÔÖ±½Ó½Ðºô½Ð sleep_on µÈ function¡£Òª½« wq É쵀 process ½ÐÐÑ¡£Ö»Òªºô½Ð wake_up µÈ function ¾Í¿ÉÒÔÁË.
¡¡¡¡
¡¡¡¡¾ÍÎÒËùÖª£¬wait_queue Ìṩ4¸ö function ¿ÉÒÔʹÓã¬Á½¸öÊÇÓÃÀ´½« process ¼Óµ½ wait_queue µÄ:
¡¡¡¡
[code]¡¡¡¡sleep_on( struct wait_queue **wq );
¡¡¡¡interruptible_sleep_on( struct wait_queue **wq );[/code]
¡¡¡¡
¡¡¡¡ÁíÍâÁ½¸öÔòÊǽ«process´Ówait_queueÉϽÐÐѵġ£
¡¡¡¡
[code]¡¡¡¡wake_up( struct wait_queue **wq );
¡¡¡¡wake_up_interruptible( struct wait_queue **wq );[/code]
¡¡¡¡
¡¡¡¡ÎÒÏÖÔÚÀ´½âÊÍÒ»ÏÂΪʲô»áÓÐÁ½×é¡£ÓÐ interruptible µÄÄÇÒ»×éÊÇÕâÑù×ӵġ£µ±ÎÒÃÇÈ¥ read Ò»¸öûÓÐ×ÊÁϿɹ©¶ÁÈ¡µÄ socket ʱ£¬process »á block ÔÚÄÇÀï¡£Èç¹ûÎÒÃÇ´Ëʱ°´Ï Ctrl+C£¬ÄÇ read() ¾Í»á´«»Ø EINTR¡£ÏñÕâÖÖµÄ block IO ¾ÍÊÇʹÓà interruptible_sleep_on() ×öµ½µÄ¡£Ò²¾ÍÊÇ˵£¬Èç¹ûÄãÊÇÓà interruptible_sleep_on() À´½« process ·Åµ½ wait_queue ʱ£¬Èç¹ûÓÐÈËËÍÒ»¸ö signal ¸øÕâ¸ö process£¬ÄÇËü¾Í»á×Ô¶¯´Ó wait_queue ÖÐÐÑÀ´¡£µ«ÊÇÈç¹ûÄãÊÇÓà sleep_on() °Ñ process ·Åµ½ wq ÖеĻ°£¬ÄDz»¹ÜÄãËÍÈÎºÎµÄ signal ¸øËü£¬Ëü»¹ÊDz»»áÀíÄãµÄ¡£³ý·ÇÄãÊÇʹÓà wake_up() ½«Ëü½ÐÐÑ¡£sleep ÓÐÁ½×é¡£wake_up Ò²ÓÐÁ½×é¡£wake_up_interruptible() »á½« wq ÖÐʹÓà interruptible_sleep_on() µÄ process ½ÐÐÑ¡£ÖÁÓÚ wake_up() ÔòÊǻὫ wq ÖÐËùÓÐµÄ process ½ÐÐÑ¡£°üÀ¨Ê¹Óà interruptible_sleep_on() µÄ process¡£
¡¡¡¡
¡¡¡¡ÔÚʹÓà wait_queue ֮ǰÓÐÒ»µãÐèÒªÌرðµÄСÐÄ£¬ºô½Ð interruptible_sleep_on() ÒÔ¼° sleep_on() µÄ function ±ØÐëÒªÊÇ reentrant¡£¼òµ¥µÄ˵£¬reentrant µÄÒâ˼ÊÇ˵´Ë function²»»á¸Ä±äÈÎºÎµÄ global variable£¬»òÕßÊDz»»á depend on ÈÎºÎµÄ global variable£¬»òÕßÊÇÔÚºô½Ð interruptible_sleep_on() »ò sleep_on() Ö®ºó²»»á depend on ÈÎºÎµÄ global variable¡£ÒòΪµ±´Ë function ºô½Ð sleep_on() ʱ£¬Ä¿Ç°µÄ process »á±»ÔÝÍ£Ö´ÐС£¿ÉÄÜÁíÒ»¸ö process ÓÖ»áºô½Ð´Ë function¡£Èô֮ǰµÄ process ½«Ä³Ð© information ´æÔÚ global variable£¬µÈËü»Ö¸´Ö´ÐÐʱҪʹÓ㬽á¹ûµÚ¶þÐг̽øÀ´ÁË£¬ÓÖ°ÑÕâ¸ö global variable ¸ÄµôÁË¡£µÈµÚÒ»¸ö process »Ö¸´Ö´ÐÐʱ£¬·ÅÔÚ global variable ÖÐµÄ information ¶¼±äÁË¡£²úÉúµÄ½á¹û¿ÖžͲ»ÊÇÎÒÃÇËùÄÜÏëÏóÁË¡£Æäʵ£¬´Ó process Ö´ÐÐÖ¸Áîµ½´Ë function ÖÐËùºô½ÐµÄ function ¶¼Ó¦¸ÃÊÇÒª reentrant µÄ¡£²»È»£¬ºÜÓпÉÄÜ»¹ÊÇ»áÓÐÉÏÊöµÄÇéÐη¢Éú.
¡¡¡¡
¡¡¡¡ÓÉÓÚ wait_queue ÊÇ kernel ËùÌṩµÄ£¬ËùÒÔ£¬Õâ¸öÀý×Ó±ØÐëÒª·Åµ½ kernel ÀïÈ¥Ö´ÐС£ÎÒʹÓõÄÕâ¸öÀý×ÓÊÇÒ»¸ö¼òµ¥µÄ driver¡£Ëü»á maintain Ò»¸ö buffer£¬´óСÊÇ 8192 bytes¡£Ìṩ read¸ú write µÄ¹¦ÄÜ¡£µ± buffer ÖÐûÓÐ×ÊÁÏʱ£¬read() »áÂíÉÏ´«»Ø£¬Ò²¾ÍÊDz»×ö block IO¡£¶øµ± write buffer ʱ£¬Èç¹ûºô½Ð write() ʱ£¬¿Õ¼äÒÑÂú»òдÈëµÄ×ÊÁÏ±È buffer ´óʱ£¬¾Í»á±» block ס£¬Ö±µ½ÓÐÈ˽« buffer ÀïµÄ×ÊÁ϶Á³öÀ´ÎªÖ¹¡£ÔÚ write buffer µÄ³ÌÐò´úÂëÖУ¬ÎÒÃÇʹÓà wait_queue À´×öµ½ block IO µÄ¹¦ÄÜ¡£ÔÚÕâÀÎһὫ´Ë driver д³É module£¬·½±ã¼ÓÔØ kernel¡£
¡¡¡¡
¡¡¡¡µÚÒ»²½£¬Õâ¸ö driver ÊÇÒ»¸ö¼òµ¥µÄ character device driver¡£ËùÒÔ£¬ÎÒÃÇÏÈÔÚ /dev ϲúÉúÒ»¸ö character device¡£major number ÎÒÃÇÕÒÒ»¸ö±È½ÏûÈËʹÓõģ¬ÏñÊÇ 54£¬minor number ¾ÍÓà 0¡£½Ó×ÅÏÂÒ»¸öÃüÁî.
¡¡¡¡
[code]¡¡¡¡mknod /dev/buf c 54 0[/code]
¡¡¡¡
¡¡¡¡mknod ÊÇÓÃÀ´²úÉú special file µÄ command¡£/dev/buf ±íʾҪ²úÉú½Ð buf µÄµµ°¸£¬Î»ÓÚ /dev Ï¡£ c ±íʾËüÊÇÒ»¸ö character device¡£54 ΪÆä major number£¬0 ÔòÊÇËüµÄ minor number¡£ÓÐ¹Ø character device driver µÄд·¨¡£Óлú»áÎÒÔÙ¸ú¸÷λ½éÉÜ£¬ÓÉÓÚÕâ´ÎÊǽ² wait_queue£¬ËùÒÔ£¬¾Í²»ÔÙ¶àÌá driver ·½ÃæµÄ¶«Î÷.
¡¡¡¡
¡¡¡¡µÚ¶þ²½£¬ÎÒÃÇҪдһ¸ö module£¬µ×ÏÂÊÇÕâ¸ö module µÄ³ÌÐò´úÂë:
¡¡¡¡
[code]¡¡¡¡buf.c
¡¡¡¡#define MODULE
¡¡¡¡#include
¡¡¡¡#include
¡¡¡¡#include
¡¡¡¡#include
¡¡¡¡#include
¡¡¡¡#define BUF_LEN 8192[/code]
ÎÄÕÂÆÀÂÛ

¹²ÓÐ 0 ÌõÆÀÂÛ