×÷ÕߣºEvan Jones
·Ò룺Ñî˶
ÔÚ³ÌÐòÔÚÔËÐеÄʱºò£¬Í¨³£¶¼ÊÇÖ»ÓÐÒ»ÌõÖ÷Ïߵģ¬ÓÐЩʱºò£¬ÕâÊÇЧÂʲ»¸ßµÄ¡£Óкܶà³ÌÐò±ØÐëÒªÄÜͬʱ×öºÜ¶à¹¤×÷¡£±ÈÈç˵£¬GUI³ÌÐò±ØÐëÔÚ´¦Àí³ÌÐòÂß¼µÄͬʱÖØ»½çÃ棬ÏìÓ¦Óû§ÊäÈë¡£Web·þÎñÆ÷±ØÐëͬʱÏò³É°ÙÉÏǧµÄ¿Í»§·¢ËÍÐÅÏ¢¡£Ï߳̿ÉÒÔ½â¾öÕâЩÄÑÌâ¡£ËùÓеÄÏÖ´ú²Ù×÷ϵͳ¶¼ÌṩÏ߳̿⣬±ÈÈç±ê×¼PosixÏ̡߳£ÌرðÊÇ£¬ÎÒ¶ÔÏ̵߳Ť×÷ÔÀíÊ®·ÖºÃÆ棬ËùÒÔÔÚѧϰÁËһЩCºÍLinuxÄں˵Ä֪ʶºó£¬ÎÒ¿ªÊ¼½¨Á¢×Ô¼ºµÄÏ߳̿⡣
¶àÈÎÎñ
ÔÚ´«Í³µÄ²Ù×÷ϵͳÖУ¬ÌṩÁËʵÏÖ¶àÈÎÎñµÄÁ½ÖÖ¹¤¾ß£¬Ò»ÖÖÊǽø³Ì£¬Ò»ÖÖÊÇÏ̡߳£
½ø³Ì
ÿ¸ö³ÌÐò¶¼ÊǶÀÁ¢µÄ½ø³Ì¡£²Ù×÷ϵͳÔÚËùÓнø³Ì¼ä·ÖÅä×ÊÔ´£¬²¢ÇÒΪÁË·ÀÖ¹Ò»¸ö½ø³ÌÐÞ¸ÄÆäËû½ø³ÌµÄ×ÊÔ´£¬½ø³Ì¼äÊDZ˴ËÍêÈ«¶ÀÁ¢µÄ¡£µ«ÊÇ£¬¶à¸ö½ø³ÌÅäºÏÍê³ÉÒ»ÏîÈÎÎñÒ²ÊǺܳ£¼ûµÄ¡£±ÈÈç˵£¬Í¼1չʾÁËÎÒµÄLinuxϵͳÏÂͬʱ½øÐеĽø³Ì£¬ÆäÖÐÓÐ4¸ö½ø³ÌÖ´ÐÐmozilla-bin¡£ÔÚÕâÖÖÇé¿öÏ£¬½ø³Ì¼äÐèÒªÏ໥ͨÐÅ£¬Òò´Ë²Ù×÷ϵͳÌṩÁ˽ø³Ì¼äͨÐÅ(IPC)µÄ¹¤¾ß£¬±ÈÈçÓÐÐźţ¬¹²ÏíÄÚ´æºÍ¹ÜµÀ¡£
Process ID Command
1 init
142 /sbin/syslogd
183 /usr/bin/X11/X
266 esd
270 sawfish
275 panel
277 gmc
279 gnome-terminal
291 bash
319 /usr/bin/mozilla-bin
341 /usr/bin/scite
344 /usr/bin/mozilla-bin
345 /usr/bin/mozilla-bin
346 /usr/bin/mozilla-bin
2568 ps
ͼ1 LinuxϵͳÉϵĽø³ÌÁбí
Ïß³Ì
½ø³Ì¼äͨÐÅÊǷdz£¼òµ¥ºÍ±ãÓÚʹÓõģ¬µ«ÊÇ£¬Èç¹ûÓкܶà½ø³ÌÐèÒª¹²Ïí±Ë´ËµÄ×ÊÔ´£¬Ä£Ð;ͻá±äµÃÊ®·Ö¸´ÔÓ¡£Ïß³ÌÌṩÁËÒ»ÖÖ½â¾öÕâÀàÎÊÌâµÄ¼òµ¥ºÍ¸ßЧµÄ·½·¨¡£Ò»¸ö½ø³Ì¿ÉÒÔº¬Óжà¸öỊ̈߳¬³ýÁË»·¾³ÉÏÏÂÎÄ(¶ÑÕ»ºÍCPU¼Ä´æÆ÷)ÒÔÍ⣬ËùÓеÄ×ÊÔ´ÔÚÏ̼߳䶼Êǹ²ÏíµÄ¡£Òò´Ë£¬Èç¹ûÒ»¸öÏß³ÌÐÞ¸ÄÁËij¸ö¹²Ïí×ÊÔ´£¬ÔòÕâÖָıä¶ÔÓÚÆäËüÏß³ÌÒ²ÊǿɼûµÄ¡£Ï̵߳Äȱµã¾ÍÊÇÒýÈëÁËÒ»¸öÐÂÎÊÌ⣬¼´Òª±ÜÃâÁ½¸öÏß³Ìͬʱ·ÃÎÊijһ¸ö¹²Ïí×ÊÔ´¡£
ÄÚºËÏß³Ì
ÏÖ´ú²Ù×÷ϵͳÔÚÄں˼¶ÉÏÖ§³ÖÏ̡߳£ÕâÒâζ×ÅÏß³ÌÖ±½ÓÓɲÙ×÷ϵͳµÄµ÷¶ÈÆ÷½øÐе÷¶È£¬Õâ¿ÉÒÔ´øÀ´´ó·ù¶ÈµÄÐÔÄÜÌáÉý¡£ÄÚºËÏ̵߳ÄȱµãÊÇÏß³ÌÇл»µÄ»¨Ïú±È½Ï´ó£¬Òò´Ë²¢·¢¶à¸öÏ߳̿ÉÄܱȵ¥Ï̵߳ÄЧÂÊÒªµÍ£¬ÒòΪÏß³ÌÇл»Õ¼ÓÃÁËÒ»¶¨µÄʱ¼ä¡£ÕâÒ²Êǵ¥Ï̷߳þÎñÆ÷£¬Èçthttpd£¬Òª±È¶àÏ̷߳þÎñÆ÷£¬ÈçApacheÐÔÄܺõÄÔÒò¡£JAWS research project¶ÔÓò»Í¬¶àÈÎÎñ·½·¨ÊµÏÖµÄweb·þÎñÆ÷µÄÐÔÄÜ×÷Á˺ÜÉîÈëµÄ·ÖÎö¡£
Óû§Ïß³Ì
Ïß³ÌÒ²¿ÉÒÔÔÚÓû§¼¶ÉÏʵÏÖ£¬ÕâÒâζ׎øÐÐÏ̵߳÷¶ÈÊÇÓɳÌÐò×ÔÉí»òÏ߳̿âÀ´Íê³ÉµÄ¡£Èç¹ûÏß³ÌÔÚÓû§¼¶ÉÏʵÏÖ£¬Í¬ÑùÒ²»áÓкܴóµÄÏß³ÌÇл»¿ªÏú£¬µ«ÊÇ£¬ÕâÖÖ¿ªÏúÒª±ÈÔÚÄں˼¶µÄÏß³ÌÇл»Ð¡ºÜ¶à¡£ÓÐЩʱºò£¬Óû§Ï̱߳»³ÆΪfiber(Ï˳Ì)£¬°µÊ¾×ÅËüÒª±ÈÄÚºËÏ̡߳°Çᡱ¡£Ò»¸ö¼òµ¥µÄÏ߳̿â
ΪÁËÍêÈ«ÍæתÕâЩ¸ÅÄlibfiberµ®ÉúÁË¡£ËüʵÏÖÁËÓû§Ï̺߳ÍÄÚºËÏ̡߳£¸ÃÏ߳̿â½ö½öʵÏÖÁËÏ̵߳Ĵ´½¨£¬Ïú»Ù¼°µ÷¶È¡£ËüÖ»Äܱ»ÓÃ×÷½Ìѧ£¬ÒòΪ»¹ÓкܶàÐźźÍͬ²½µÄÎÊÌâûÓнâ¾ö¡£ÔÚ±àдÕæʵµÄ³ÌÐòʱ£¬¿ÉÒÔʹÓÃÄÚºËÏ߳̿âpthreads»òÓû§Ï߳̿âGNU Portable Threads (Pth)¡£
Libfiber ½Ó¿Ú
void initFibers();
³õʼ»¯Ï߳̿âµÄÄÚ²¿Êý¾Ý½á¹¹¡£±ØÐëÔÚʹÓÃÆäËûº¯ÊýÇ°µ÷Óá£
int spawnFiber( void (*func)(void) );
´´½¨Ị̈߳¬¸ÃÏ߳̽«»áÖ´Ðиø¶¨µÄº¯Êý¡£³É¹¦·µ»ØÁ㣬´íÎ󷵻طÇÁã¡£
void fiberYield();
Ö÷¶¯·ÅÆúCPU¡£ÔÚÄÚºËÏß³ÌʵÏÖÖУ¬Ö»ÊǼòµ¥µÄµ÷ÓÃsched_yield¡£
void waitForAllFibers();
µÈ´ýËùÓÐÏß³ÌÍ˳ö£¬ÊÍ·Å×ÊÔ´¡£Èç¹ûÔÚÓû§Ïß³ÌÖе÷Óã¬Ö»ÓÐËùÓÐÆäËüÏß³ÌÈ«²¿·µ»Ø¸Ãº¯Êý²Å»á·µ»Ø£»Èç¹ûÔÚÄÚºËÏß³ÌÖе÷Óã¬Ëü»áÁ¢¼´·µ»Ø¡£³É¹¦·µ»ØÁ㣬´íÎ󷵻طÇÁã¡£
ͼ2ÏÔʾµÄÊÇÓøÃÏ߳̿â±àдµÄÑùÀý³ÌÐò¡£Ëü´´½¨ÁËÈý¸öỊ̈߳¬·Ö±ðÖ´Ðв»Í¬µÄº¯Êý£¬µÈ´ýËùÓÐÏß³ÌÍ˳öºó·µ»Ø¡£
int main()
{
// Initialize the fiber library
initFibers();
// Go fibers!
spawnFiber( &fiber1 );
spawnFiber( &fibonacchi );
spawnFiber( &squares );
// Since these are not preemptive, we must allow them to run
waitForAllFibers();
// The program quits
return 0;
}
ͼ2 ʹÓÃÏ߳̿âµÄÑùÀý³ÌÐò
ÔÚLinuxÉÏʵÏÖÄÚºËÏß³Ì
LinuxʹÓÃÒ»¸öÌØÊâµÄ·½·¨ÊµÏÖÏ̡߳£ÔÚLinuxÉÏ£¬½ø³ÌºÍÏß³ÌÔÚ±¾ÖÊÉÏÊÇÒ»ÑùµÄ£¬ËüÃǶ¼±»ÈÏΪÊÇÈÎÎñ¡£Î¨Ò»µÄÇø±ðÊÇÏֳɹ²ÏíÄÚ´æ¿Õ¼ä£¬ÎļþÃèÊö·ûºÍÐźŴ¦Àí³ÌÐò(ͨ³£Çé¿öÏÂ)¡£ÔÚLinux Kernel Mailing ListÉÏ£¬Linus Torvalds·¢¹ýÒ»¸ö¾µäµÄÌû×ÓÀ´²ûÊöÕâÖÖʵÏÖ·½Ê½µÄÓŵ㡣
ÔÚLinuxÉÏ£¬ÄÚºËÏ߳̿ÉÒÔͨ¹ýϵͳµ÷ÓÃcloneÀ´´´½¨¡£Õâ¸öϵͳµ÷ÓøúforkÏàËÆ£¬¶¼ÊÇ´´½¨Ò»¸öÈÎÎñ¡£Ö»²»¹ýclone¿ÉÒÔÖ¸¶¨¹²ÏíÄÄЩ×ÊÔ´¡£ÔÚ´´½¨Ïß³Ìʱ£¬ÎÒÃÇ¿ÉÒÔ¹²Ïí¾¡¿ÉÄܶàµÄ×ÊÔ´£ºÄÚ´æ¿Õ¼ä£¬ÎļþÃèÊö·ûºÍÐźŴ¦Àíº¯Êý¡£µ±Ïß³ÌÍ˳ö£¬·¢³öSIGCHLDÐźÅʱ£¬wait½«»á·µ»Ø¡£
µÚÒ»¸öÌôÕ½ÊÇΪÏ̷߳ÖÅäÕ»¿Õ¼ä¡£ÔÚlibfierÖÐʹÓõÄÊÇ×î¼òµ¥µÄ·½·¨£¬¼´Ê¹ÓÃmallocÔÚ¶ÑÖзÖÅäÕ»¿Õ¼ä¡£ÕâÒâζ×űØÐëÒª¹À¼ÆÒ»¸öÕ»µÄ×î´óÖµ¡£Èç¹ûÕ»ÔÚʹÓÃʱ³¬³öÁË×î´óÖµ£¬»áÒýÆðÄÚ´æ³åÍ»¡£ÔÚbb_threadsÖУ¬ÊÇʹÓÃmprotectÔÚÕ»µ×´´½¨Ò»¸öbarrier£¬ÕâÑùÔÚÕ»Òç³öµÄʱºò»áÒý·¢¶Î´íÎó¡£×îºÃµÄ·½·¨ÊÇLinux pthreadsµÄʵÏÖ£¬ÊÇʹÓÃmmapÀ´·ÖÅäÄڴ棬ÕâÑùµÄ»°£¬ÄÚ´æËæÐèËæ·ÖÅ䣬Èç¹ûϵͳ²»ÄÜ·ÖÅäÁíÍâµÄÄڴ棬½«»á²úÉúsegmentation violation¡£
´«µÝ¸øcloneµÄÕ»Ö¸Õë±ØÐëÖ¸ÏòÕ»¶¥£¬ÒòΪÔÚ¶àÊý´¦ÀíÆ÷ÖУ¬Õ»ÊÇÏòÏÂÉú³¤µÄ¡£ÎªÁ˱ÜÃâÄÚ´æй¶£¬Ïß³ÌÍ˳öʱ±ØÐëÊÍ·ÅÕ»¿Õ¼ä¡£Libfiber¿âʹÓÃwaitµÈ´ýÏß³ÌÍ˳ö£¬È»ºóʹÓÃfreeÊÍ·ÅÕ»¿Õ¼ä¡£Í¼3ÏÔʾÁË´´½¨Ï̵߳ÄÀý×Ó¡£Çëͨ¹ýlibfiber-clone.c²é¿´ÍêÕûµÄʵÏÖ¡£Èç¹ûÏëÁ˽âLinux pthreadÈçºÎʵÏÖ´´½¨Ị̈߳¬Çë¿´"The Fibers of Threads"¡£
#include
#include
#include
#include
#include
#include
// 64kB stack
#define FIBER_STACK 1024*64
// The child thread will execute this function
int threadFunction( void* argument )
{
printf( "child thread exiting\n" );
return 0;
}
int main()
{
void* stack;
pid_t pid;
// Allocate the stack
stack = malloc( FIBER_STACK );
if ( stack == 0 )
{
perror( "malloc: could not allocate stack" );
exit( 1 );
}
printf( "Creating child thread\n" );
// Call the clone system call to create the child thread
pid = clone( &threadFunction, (char*) stack + FIBER_STACK,
SIGCHLD | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_VM, 0 );
if ( pid == -1 )
{
perror( "clone" );
exit( 2 );
}
// Wait for the child thread to exit
pid = waitpid( pid, 0, 0 );
if ( pid == -1 )
{
perror( "waitpid" );
exit( 3 );
}
// Free the stack
free( stack );
printf( "Child thread returned and stack freed.\n" );
return 0;
}
ͼ3 ÓÃcloneʵÏÖÏß³Ì
ʹÓÃmakecontextʵÏÖÓû§Ïß³Ì
ÏÖ´úUnixϵͳ¶¼ÔÚucontext.hÖÐÌṩÓÃÓÚÉÏÏÂÎÄÇл»µÄº¯Êý£¬ÕâЩº¯ÊýÓÐgetcontext, setcontext£¬swapcontext ºÍmakecontext¡£ÆäÖУ¬getcontextÓÃÓÚ±£´æµ±Ç°ÉÏÏÂÎÄ£¬setcontextÓÃÓÚÇл»ÉÏÏÂÎÄ£¬swapcontext»á±£´æµ±Ç°ÉÏÏÂÎIJ¢Çл»µ½ÁíÒ»¸öÉÏÏÂÎÄ£¬makecontext´´½¨Ò»¸öеÄÉÏÏÂÎÄ¡£ÊµÏÖÓû§Ï̵߳Ĺý³ÌÊÇ£ºÎÒÃÇÊ×Ïȵ÷ÓÃgetcontext»ñµÃµ±Ç°ÉÏÏÂÎÄ£¬È»ºóÐÞ¸Äucontext_tÖ¸¶¨ÐµÄÉÏÏÂÎÄ¡£Í¬ÑùµÄ£¬ÎÒÃÇÐèÒª¿ª±ÙÕ»¿Õ¼ä£¬µ«ÊÇÕâ´ÎʵÏÖµÄÏ߳̿âÒªÉæ¼°Õ»Éú³¤µÄ·½Ïò¡£È»ºóÎÒÃǵ÷ÓÃmakecontextÇл»ÉÏÏÂÎÄ£¬²¢Ö¸¶¨Óû§Ïß³ÌÖÐÒªÖ´Ðеĺ¯Êý¡£
ÔÚÕâÖÖʵÏÖÖл¹ÓÐÒ»¸öÌôÕ½£¬¼´Ò»¸öÏ̱߳ØÐë¿ÉÒÔÖ÷¶¯ÈóöCPU¸øÆäËüÏ̡߳£swapcontextº¯Êý¿ÉÒÔÍê³ÉÕâ¸öÈÎÎñ£¬Í¼4չʾÁËÒ»¸öÕâÖÖʵÏÖµÄÑùÀý³ÌÐò£¬childÏ̺߳ÍparentÏ̲߳»¶ÏÇл»ÒÔ´ïµ½¶àÏ̵߳ÄЧ¹û¡£ÔÚlibfiber-uc.cÎļþÖпÉÒÔ¿´µ½ÍêÕûµÄʵÏÖ¡£
#include
#include
#include
// 64kB stack
#define FIBER_STACK 1024*64
ucontext_t child, parent;
// The child thread will execute this function
void threadFunction()
{
printf( "Child fiber yielding to parent" );
swapcontext( &child, &parent );
printf( "Child thread exiting\n" );
swapcontext( &child, &parent );
}
int main()
{
// Get the current execution context
getcontext( &child );
// Modify the context to a new stack
child.uc_link = 0;
child.uc_stack.ss_sp = malloc( FIBER_STACK );
child.uc_stack.ss_size = FIBER_STACK;
child.uc_stack.ss_flags = 0;
if ( child.uc_stack.ss_sp == 0 )
{
perror( "malloc: Could not allocate stack" );
exit( 1 );
}
// Create the new context
printf( "Creating child fiber\n" );
makecontext( &child, &threadFunction, 0 );
// Execute the child context
printf( "Switching to child fiber\n" );
swapcontext( &parent, &child );
printf( "Switching to child fiber again\n" );
swapcontext( &parent, &child );
// Free the stack
free( child.uc_stack.ss_sp );
printf( "Child fiber returned and stack freed\n" );
return 0;
}
ͼ4ÓÃmakecontextʵÏÖÏß³Ì
½áÂÛ
ʵÏÖÒ»¸ö¼òµ¥µÄÏ߳̿âlibfiber¿ÉÒÔÈÃÎÒÃǸüºÃµÄÀí½âÏ߳̿âÊÇÈçºÎʵÏÖÏ̵߳ģ¬µ±ÎÒÃÇÔÚ·ÖÎö²»Í¬¶àÏ̹߳¤¾ßµÄʱºò£¬ÉÏÃæµÄÕâЩ¾Ñé¾Í»áÅÉÉÏÓó¡¡£±¾Ï߳̿âÊÇÔÚLinux¿ª·¢²¢²âÊԵģ¬µ«ÊÇÕæÕýµÄÏ߳̿âÓ¦¸ÃÊÇ¿ÉÒÔÒÆÖ²µ½Unixƽ̨Éϵģ¬´ÓÕâµãÉÏÀ´Ëµ£¬±¾Ï߳̿âʵÏÖµÄÄÚºËÏß³ÌÊÇLinuxרÓеģ¬ÒòΪËüÊÇÀûÓÃcloneϵͳµ÷ÓÃÀ´ÊµÏֵġ£