??xml version="1.0" encoding="utf-8" standalone="yes"?>
按照教科书上的定义,q程是资源管理的最单位,U程是程序执行的最单位。在操作pȝ设计上,从进E演化出U程Q最主要的目的就是更好的支持SMP以及减小Q进E?U程Q上下文切换开销?/p>
无论按照怎样的分法,一个进E至需要一个线E作为它的指令执行体Q进E管理着资源Q比如cpu、内存、文件等{)Q而将U程分配到某 个cpu上执行。一个进E当然可以拥有多个线E,此时Q如果进E运行在SMP机器上,它就可以同时使用多个cpu来执行各个线E,辑ֈ最大程度的q行Q以 提高效率Q同Ӟ即是在单cpu的机器上Q采用多U程模型来设计程序,正如当年采用多进E模型代替单q程模型一P使设计更z、功能更完备Q程序的?行效率也更高Q例如采用多个线E响应多个输入,而此时多U程模型所实现的功能实际上也可以用多进E模型来实现Q而与后者相比,U程的上下文切换开销比q?E要多了,从语义上来说Q同时响应多个输入这L功能Q实际上是׃n了除cpu以外的所有资源的?/p>
针对U程模型的两大意义,分别开发出了核心U程和用LU程两种U程模型Q分cȝ标准主要是线E的调度者在核内q是在核外。前者更?于ƈ发用多处理器的资源Q而后者则更多考虑的是上下文切换开销。在目前的商用系l中Q通常都将两者结合v来用,既提供核心线E以满smppȝ的需 要,也支持用U程库的方式在用h实现另一套线E机Ӟ此时一个核心线E同时成为多个用h线E的调度者。正如很多技术一P"混合"通常都能带来更高?效率Q但同时也带来更大的实现隑ֺQ出??的设计思\QLinux从一开始就没有实现混合模型的计划,但它在实C采用了另一U思\?混合"?/p>
在线E机制的具体实现上,可以在操作系l内怸实现U程Q也可以在核外实玎ͼ后者显然要求核内至实Cq程Q而前者则一般要求在核内 同时也支持进E。核心U程模型昄要求前者的支持Q而用LU程模型则不一定基于后者实现。这U差异,正如前所qͼ是两U分cL式的标准不同带来的?/p>
当核内既支持q程也支持线E时Q就可以实现U程-q程?多对?模型Q即一个进E的某个U程由核内调度,而同时它也可以作为用LU?E池的调度者,选择合适的用户U线E在其空间中q行。这是前面提到?混合"U程模型Q既可满_处理机系l的需要,也可以最大限度的减小调度开销。绝 大多数商业操作系l(如Digital Unix、Solaris、IrixQ都采用的这U能够完全实现POSIX1003.1c标准的线E模型。在核外实现的线E又可以分ؓ"一对一"?多对 一"两种模型Q前者用一个核心进E(也许是轻量进E)对应一个线E,线E调度等同于q程调度Q交l核心完成,而后者则完全在核外实现多U程Q调度也在用 h完成。后者就是前面提到的单纯的用LU程模型的实现方式,昄Q这U核外的U程调度器实际上只需要完成线E运行栈的切换,调度开销非常,但同时因 为核心信P无论是同步的q是异步的)都是以进Eؓ单位的,因而无法定位到U程Q所以这U实现方式不能用于多处理器系l,而这个需求正变得来大Q因 此,在现实中Q纯用户U线E的实现Q除法研究目的以外Q几乎已l消׃?/p>
Linux内核只提供了轻量q程的支持,限制了更高效的线E模型的实现Q但Linux着重优化了q程的调度开销Q一定程度上也I补了q?一~陷。目前最行的线E机制LinuxThreads所采用的就是线E?q程"一对一"模型Q调度交l核心,而在用户U实C个包括信号处理在内的U程 理机制。Linux-LinuxThreads的运行机制正是本文的描述重点?/p>
最初的q程定义都包含程序、资源及其执行三部分Q其中程序通常指代码,资源在操作系l层面上通常包括内存资源、IO资源、信号处理等?分,而程序的执行通常理解为执行上下文Q包括对cpu的占用,后来发展为线E。在U程概念出现以前Qؓ了减进E切换的开销Q操作系l设计者逐渐修正q程 的概念,逐渐允许进E所占有的资源从其主体剥d来,允许某些q程׃n一部分资源Q例如文件、信P数据内存Q甚至代码,q就发展量进E的概念?Linux内核?.0.x版本已l实C轻量q程Q应用程序可以通过一个统一的clone()pȝ调用接口Q用不同的参数指定创量进E还是普通进 E。在内核中,clone()调用l过参数传递和解释后会调用do_fork()Q这个核内函数同时也是fork()、vfork()pȝ调用的最l实 玎ͼ
<linux-2.4.20/kernel/fork.c> int do_fork(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size) |
其中的clone_flags取自以下宏的"?|
<linux-2.4.20/include/linux/sched.h> #define CSIGNAL 0x000000ff /* signal mask to be sent at exit */ #define CLONE_VM 0x00000100 /* set if VM shared between processes */ #define CLONE_FS 0x00000200 /* set if fs info shared between processes */ #define CLONE_FILES 0x00000400 /* set if open files shared between processes */ #define CLONE_SIGHAND 0x00000800 /* set if signal handlers and blocked signals shared */ #define CLONE_PID 0x00001000 /* set if pid shared */ #define CLONE_PTRACE 0x00002000 /* set if we want to let tracing continue on the child too */ #define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */ #define CLONE_PARENT 0x00008000 /* set if we want to have the same parent as the cloner */ #define CLONE_THREAD 0x00010000 /* Same thread group? */ #define CLONE_NEWNS 0x00020000 /* New namespace group? */ #define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD) |
在do_fork()中,不同的clone_flags导致不同的行ؓQ对于LinuxThreadsQ它使用QCLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHANDQ参数来调用clone()创徏"U程"Q表C共享内存、共享文件系l访问计数、共享文件描q符表,以及׃n信号处理方式。本 节就针对q几个参敎ͼ看看Linux内核是如何实现这些资源的׃n的?/p>
1.CLONE_VM
do_fork()需要调用copy_mm()来设|task_struct中的mm和active_mm,q两?mm_struct数据与进E所兌的内存空间相对应。如果do_fork()时指定了CLONE_VM开养Icopy_mm()把新的 task_struct中的mm和active_mm讄成与current的相同,同时提高该mm_struct的用者数?Qmm_struct::mm_usersQ。也是_轻量U进E与父进E共享内存地址I间Q由下图C意可以看出mm_struct在进E中的地位:
2.CLONE_FS
task_struct中利用fsQstruct fs_struct *Q记录了q程所在文件系l的根目录和当前目录信息Qdo_fork()时调用copy_fs()复制了这个结构;而对于轻量q程则仅增加 fs->count计数Q与父进E共享相同的fs_struct。也是_轻量U进E没有独立的文gpȝ相关的信息,q程中Q何一个线E改变当?目录、根目录{信息都直接媄响到其他U程?/p>
3.CLONE_FILES
一个进E可能打开了一些文Ӟ在进E结构task_struct中利用filesQstruct files_struct *Q来保存q程打开的文件结构(struct fileQ信息,do_fork()中调用了copy_files()来处理这个进E属性;轻量U进E与父进E是׃n该结构的Qcopy_files() 时仅增加files->count计数。这一׃n使得MU程都能讉Kq程所l护的打开文gQ对它们的操作会直接反映到进E中的其他线E?/p>
4.CLONE_SIGHAND
每一个Linuxq程都可以自行定义对信号的处理方式,在task_struct中的sigQstruct signal_structQ中使用一个struct k_sigactionl构的数l来保存q个配置信息Qdo_fork()中的copy_sighand()负责复制该信息;轻量U进E不q行复制Q而仅 仅增加signal_struct::count计数Q与父进E共享该l构。也是_子进E与父进E的信号处理方式完全相同Q而且可以怺更改?/p>
do_fork()中所做的工作很多Q在此不详细描述。对于SMPpȝQ所有的q程fork出来后,都被分配C父进E相同的cpu上,一直到该进E被调度时才会进行cpu选择?/p>
管Linux支持轻量U进E,但ƈ不能说它支持核心U程Q因为Linux?U程"?q程"实际上处于一个调度层ơ,׃n一?q程标识W空_q种限制使得不可能在Linux上实现完全意义上的POSIXU程机制Q因此众多的LinuxU程库实现尝试都只能可能实现POSIX 的绝大部分语义,q在功能上尽可能D?/p>
LinuxThreads是目前Linuxq_上用最为广泛的U程库,由Xavier Leroy (Xavier.Leroy@inria.fr)负责开发完成,q已l定在GLIBC中发行。它所实现的就是基于核心轻量q程?一对一"U程模型Q一 个线E实体对应一个核心轻量q程Q而线E之间的理在核外函数库中实现?/p>
LinuxThreads定义了一个struct _pthread_descr_struct数据l构来描q线E,q用全局数组变量__pthread_handles来描q和引用q程所辖线E。在 __pthread_handles中的前两,LinuxThreads定义了两个全局的系l线E:__pthread_initial_thread 和__pthread_manager_threadQƈ用__pthread_main_thread表征 __pthread_manager_thread的父U程Q初始ؓ__pthread_initial_threadQ?/p>
struct _pthread_descr_struct是一个双环链表结构,__pthread_manager_thread所在的链表仅包括它一个元素,实际 上,__pthread_manager_thread是一个特D线E,LinuxThreads仅用了其中的errno、p_pid?p_priority{三个域。而__pthread_main_thread所在的铑ֈ进E中所有用LE串在了一赗经q一pd pthread_create()之后形成的__pthread_handles数组如下图所C:
新创建的U程首先在__pthread_handles数组中占据一,然后通过数据l构中的链指针连入以__pthread_main_thread为首指针的链表中。这个链表的使用在介l线E的创徏和释攄时候将提到?/p>
LinuxThreads遵@POSIX1003.1c标准Q其中对U程库的实现q行了一些范围限Ӟ比如q程最大线E数Q线E私有数 据区大小{等。在LinuxThreads的实CQ基本遵循这些限Ӟ但也q行了一定的改动Q改动的势是放松或者说扩大q些限制Qɾ~程更加方便。这 些限定宏主要集中在sysdeps/unix/sysv/linux/bits/local_lim.hQ不同^C用的文g位置不同Q中Q包括如下几 个:
每进E的U有数据key敎ͼPOSIX定义_POSIX_THREAD_KEYS_MAX?28QLinuxThreads使用 PTHREAD_KEYS_MAXQ?024Q私有数据释放时允许执行的操作数QLinuxThreads与POSIX一_定义 PTHREAD_DESTRUCTOR_ITERATIONS?Q每q程的线E数QPOSIX定义?4QLinuxThreads增大?1024QPTHREAD_THREADS_MAXQ;U程q行栈最空间大,POSIX未指定,LinuxThreads使用 PTHREAD_STACK_MINQ?6384Q字节)?/p>
"一对一"模型的好处之一是线E的调度由核心完成了Q而其他诸如线E取消、线E间的同步等工作Q都是在核外U程库中完成的。在 LinuxThreads中,专门为每一个进E构造了一个管理线E,负责处理U程相关的管理工作。当q程W一ơ调用pthread_create()创徏 一个线E的时候就会创建(__clone()Qƈ启动理U程?/p>
在一个进E空间内Q管理线E与其他U程之间通过一?理道Qmanager_pipe[2]Q?来通讯Q该道在创建管理线E之?创徏Q在成功启动了管理线E之后,理道的读端和写端分别赋给两个全局变量__pthread_manager_reader?__pthread_manager_requestQ之后,每个用户U程都通过__pthread_manager_request向管理线E发hQ?但管理线E本wƈ没有直接使用__pthread_manager_readerQ管道的ȝQmanager_pipe[0]Q是作ؓ __clone()的参C一传给理U程的,理U程的工作主要就是监听管道读端,q对从中取出的请求作出反应?/p>
创徏理U程的流E如下所C:
Q全局变量pthread_manager_request初gؓ-1Q?/p>
初始化结束后Q在__pthread_manager_thread中记录了轻量U进E号以及核外分配和管理的U程 idQ?*PTHREAD_THREADS_MAX+1q个数g会与M常规用户U程id冲突。管理线E作为pthread_create()的调用?U程的子U程q行Q而pthread_create()所创徏的那个用LE则是由理U程来调用clone()创徏Q因此实际上是管理线E的子线E?Q此处子U程的概念应该当作子q程来理解。)
__pthread_manager()是理U程的主循环所在,在进行一pd初始化工作后Q进入while(1)循环。在循环中, U程?Uؓtimeout查询Q__poll()Q管理管道的ȝ。在处理h前,查其父线E(也就是创建manager的主U程Q是否已退出,如果 已退出就退出整个进E。如果有退出的子线E需要清理,则调用pthread_reap_children()清理?/p>
然后才是d道中的hQ根据请求类型执行相应操作(switch-caseQ。具体的h处理Q源码中比较清楚Q这里就不赘qC?/p>
在LinuxThreads中,理U程的栈和用LE的栈是分离的,理U程在进E堆中通过malloc()分配一个THREAD_MANAGER_STACK_SIZE字节的区域作qq行栈?/p>
用户U程的栈分配办法随着体系l构的不同而不同,主要Ҏ两个宏定义来区分Q一个是 NEED_SEPARATE_REGISTER_STACKQ这个属性仅在IA64q_上用;另一个是FLOATING_STACK宏,在i386{少 数^C使用Q此时用LE栈ql决定具体位|ƈ提供保护。与此同Ӟ用户q可以通过U程属性结构来指定使用用户自定义的栈。因幅所限,q里只能分析 i386q_所使用的两U栈l织方式QFLOATING_STACK方式和用戯定义方式?/p>
在FLOATING_STACK方式下,LinuxThreads利用mmap()从内核空间中分配8MBI间Qi386pȝ~省的最 大栈I间大小Q如果有q行限制QrlimitQ,则按照运行限制设|)Q用mprotect()讄其中W一ؓ非访问区。该8MI间的功能分配如?图:
低地址被保护的面用来监测栈溢出?/p>
对于用户指定的栈Q在按照指针对界后,讄U程栈顶Qƈ计算出栈底,不做保护Q正性由用户自己保证?/p>
不论哪种l织方式Q线E描q结构L位于栈顶紧邻堆栈的位|?/p>
每个LinuxThreadsU程都同时具有线Eid和进EidQ其中进Eid是内核所l护的进E号Q而线Eid则由LinuxThreads分配和维护?/p>
__pthread_initial_thread的线Eid?PTHREAD_THREADS_MAXQ__pthread_manager_thread的是2*PTHREAD_THREADS_MAX+1Q第一 个用LE的U程id为PTHREAD_THREADS_MAX+2Q此后第n个用LE的U程id遵@以下公式Q?/p>
tid=n*PTHREAD_THREADS_MAX+n+1 |
q种分配方式保证了进E中所有的U程Q包括已l退出)都不会有相同的线EidQ而线Eid的类型pthread_t定义为无W号长整型(unsigned long intQ,也保证了有理qq行旉内线Eid不会重复?/p>
从线Eid查找U程数据l构是在pthread_handle()函数中完成的Q实际上只是线E号按PTHREAD_THREADS_MAX取模Q得到的是该线E在__pthread_handles中的索引?/p>
在pthread_create()向管理线E发送REQ_CREATEh之后Q管理线E即调用 pthread_handle_create()创徏新线E。分配栈、设|thread属性后Q以pthread_start_thread()为函数入 口调用__clone()创徏q启动新U程。pthread_start_thread()d自n的进Eid号存入线E描q结构中QƈҎ其中记录的调 度方法配|调度。一切准备就l后Q再调用真正的线E执行函敎ͼq在此函数返回后调用pthread_exit()清理现场?/p>
׃Linux内核的限制以及实现难度等{原因,LinuxThreadsq不是完全POSIX兼容的,在它的发行README中有说明?/p>
1)q程id问题
q个不是最关键的不I引v的原因牵涉到LinuxThreads?一对一"模型?/p>
Linux内核q不支持真正意义上的U程QLinuxThreads是用与普通进E具有同样内核调度视囄轻量U进E来实现U程支持 的。这些轻量q程拥有独立的进EidQ在q程调度、信号处理、IO{方面n有与普通进E一L能力。在源码阅读者看来,是Linux内核?clone()没有实现对CLONE_PID参数的支持?/p>
在内核do_fork()中对CLONE_PID的处理是q样的:
if (clone_flags & CLONE_PID) { if (current->pid) goto fork_out; } |
q段代码表明Q目前的Linux内核仅在pid?的时候认可CLONE_PID参数Q实际上Q仅在SMP初始化,手工创徏q程的时候才会用CLONE_PID参数?/p>
按照POSIX定义Q同一q程的所有线E应该共享一个进Eid和父q程idQ这在目前的"一对一"模型下是无法实现的?/p>
2)信号处理问题
׃异步信号是内总q程为单位分发的Q而LinuxThreads的每个线E对内核来说都是一个进E,且没有实?U程l?Q因此,某些语义不符合POSIX标准Q比如没有实现向q程中所有线E发送信PREADMEҎ作了说明?/p>
如果核心不提供实时信PLinuxThreads用SIGUSR1和SIGUSR2作ؓ内部使用的restart和cancel 信号Q这样应用程序就不能使用q两个原本ؓ用户保留的信号了。在Linux kernel 2.1.60以后的版本都支持扩展的实时信P从_SIGRTMIN到_SIGRTMAXQ,因此不存在这个问题?/p>
某些信号的缺省动作难以在现行体系上实玎ͼ比如SIGSTOP和SIGCONTQLinuxThreads只能一个线E挂P而无法挂h个进E?/p>
3)U程L问题
LinuxThreads每个进E的U程最大数目定义ؓ1024Q但实际上这个数D受到整个pȝ的总进E数限制Q这又是׃U程其实是核心进E?/p>
在kernel 2.4.x中,采用一套全新的总进E数计算ҎQ得总进E数基本上仅受限于物理内存的大小Q计公式在kernel/fork.c的fork_init()函数中:
max_threads = mempages / (THREAD_SIZE/PAGE_SIZE) / 8 |
在i386上,THREAD_SIZE=2*PAGE_SIZEQPAGE_SIZE=2^12Q?KBQ,mempages=物理?存大?PAGE_SIZEQ对?56M的内存的机器Qmempages=256*2^20/2^12=256*2^8Q此时最大线E数?096?/p>
但ؓ了保证每个用P除了rootQ的q程L不至于占用一半以上物理内存,fork_init()中l指定:
init_task.rlim[RLIMIT_NPROC].rlim_cur = max_threads/2; init_task.rlim[RLIMIT_NPROC].rlim_max = max_threads/2; |
q些q程数目的检查都在do_fork()中进行,因此Q对于LinuxThreads来说Q线EL同时受这三个因素的限制?/p>
4)理U程问题
理U程Ҏ成ؓ瓉Q这是这U结构的通病Q同Ӟ理U程又负责用LE的清理工作Q因此,管理U程已经屏蔽了大部分的信P但一旦管理线E死亡,用户U程׃得不手工清理了,而且用户U程q不知道理U程的状态,之后的线E创建等h无人处理?/p>
5)同步问题
LinuxThreads中的U程同步很大E度上是建立在信号基上的Q这U通过内核复杂的信号处理机制的同步方式Q效率一直是个问题?/p>
6Q其他POSIX兼容性问?/strong>
Linux中很多系l调用,按照语义都是与进E相关的Q比如nice、setuid、setrlimit{,在目前的LinuxThreads中,q些调用都仅仅媄响调用者线E?/p>
7Q实时性问?/strong>
U程的引入有一定的实时性考虑Q但LinuxThreads暂时不支持,比如调度选项Q目前还没有实现。不仅LinuxThreads如此Q标准的Linux在实时性上考虑都很?/p>
LinuxThreads的问题,特别是兼Ҏ上的问题,严重ȝ了Linux上的跨^台应用(如ApacheQ采用多U程设计Q从?使得Linux上的U程应用一直保持在比较低的水^。在LinuxC中,已经有很多h在ؓ改进U程性能而努力,其中既包括用LU程库,也包括核心?用户U配合改q的U程库。目前最Zh看好的有两个目Q一个是RedHat公司牵头研发的NPTLQNative Posix Thread LibraryQ,另一个则是IBM投资开发的NGPTQNext Generation Posix ThreadingQ,二者都是围l完全兼容POSIX 1003.1cQ同时在核内和核外做工作以而实现多对多U程模型。这两种模型都在一定程度上弥补了LinuxThreads的缺点,且都是重L灶全新设 计的?/p>
1.NPTL
NPTL的设计目标归U_归纳Z下几点:
在技术实CQNPTL仍然采用1:1的线E模型,q合glibc和最新的Linux Kernel2.5.x开发版在信号处理、线E同步、存储管理等多方面进行了优化。和LinuxThreads不同QNPTL没有使用理U程Q核心线E?的管理直接放在核内进行,q也带了性能的优化?/p>
主要是因为核心的问题QNPTL仍然不是100%POSIX兼容的,但就性能而言相对LinuxThreads已经有很大程度上的改q了?/p>
2.NGPT
IBM的开放源码项目NGPT?003q??0日推ZE_?.2.0版,但相关的文工作q差很多。就目前所知,NGPT是基于GNU PthQGNU Portable ThreadsQ项目而实现的M:N模型Q而GNU Pth是一个经典的用户U线E库实现?/p>
按照2003q?月NGPT官方|站上的通知QNGPT考虑到NPTL日益q泛Cؓ人所接受Qؓ避免不同的线E库版本引v的乱,今后不再进行进一步开发,而今q行支持性的l护工作。也是_NGPT已经攑ּ与NPTL竞争下一代Linux POSIXU程库标准?/p>
3.其他高效U程机制
此处不能不提到Scheduler Activations。这?991q在ACM上发表的多线E内核结构媄响了很多多线E内核的设计Q其中包括Mach3.0、NetBSD和商业版?Digital UnixQ现在叫Compaq True64 UnixQ。它的实质是在用用LU程调度的同Ӟ可能地减少用户U对核心的系l调用请求,而后者往往是运行开销的重要来源。采用这U结构的U程?Ӟ实际上是l合了用LU程的灵z高效和核心U线E的实用性,因此Q包括Linux、FreeBSD在内的多个开放源码操作系l设计社区都在进行相关研 IӞ力图在本pȝ中实现Scheduler Activations?br />
转自Q?a >http://blog.chinaunix.net/uid-20556054-id-3075951.html
Linux内核对多q程和多U程的支持方式:
U程机制支持q发E序设计技术,在多处理器上能真正保证ƈ行处理。而在linux实现U程很特别,linux把所有的U程都当作进E实现。linux下线 E看h像普通进E?只是该进E和其他q程׃n资源Q如地址I间)。上q机制与Microsoft windows或是Sun Solaris实现差异很大?/p>
Linux的线E实现是在核外进行的Q核内提供的是创E的接口do_fork()。内核提供了两个pȝ调用__clone()和fork()Q最l都 用不同的参数调用do_fork()核内API?do_fork() 提供了很多参敎ͼ包括CLONE_VMQ共享内存空_、CLONE_FSQ共享文件系l信息)、CLONE_FILESQ共享文件描q符表)?CLONE_SIGHANDQ共享信号句柄表Q和CLONE_PIDQ共享进EIDQ仅Ҏ内进E,?可E有效)。当使用forkpȝ调用产生多进E?Ӟ内核调用do_fork()不用Q何共享属性,q程拥有独立的运行环境。当使用pthread_create()来创建线E时Q则最l设|了所有这 些属性来调用__clone()Q而这些参数又全部传给核内的do_fork()Q从而创建的”q程”拥有׃n的运行环境,只有栈是独立的,?__clone()传入?/p>
卻ILinux?strong style="word-wrap: break-word; ">不管是多U程~程q是多进E编E,最l都是用do_fork实现?多进E编E,只是q程创徏时的参数不同Q从而导致有不同的共享环境。LinuxU程在核内是以轻量q程的Ş式存在的Q拥有独立的q程表项Q而所有的?建、同步、删除等操作都在核外pthread库中q行。pthread 库用一个管理线E(__pthread_manager() Q每个进E独立且唯一Q来理U程的创建和l止QؓU程分配U程IDQ发送线E相关的信号Q而主U程pthread_create()Q?的调用者则通过道请求信息传l管理线E?/p>
很多朋友都说使用多线E的好处是资源占用少Q其隐含之意是说进E占用资源比U程多,对吧Q但实际上Linux下多q程是否q的点用很多资源呢Q?暂且不说q程是否比线E占用资源多Q就q程占用资源的多情况而言QLinux实是做得相当节省的。生一个多q程时肯定是要生的一点内存是要复制进 E表,即一个task_structl构Q但q个l构本n做得相当y。其它对于一个进E来说必L的数据段、代码段、堆栈段是不是全盘复制呢Q对于多 q程来说Q代码段是肯定不用复制的Q因为父q程和各子进E的代码D|相同的,数据D和堆栈D呢Q也不一定,因ؓ在Linux里广泛用的一个技术叫 copy-on-writeQ即写时拯。copy-on-write意味着什么呢Q意味着资源节省Q假设有一个变量x在父q程里存在,当这个父q程创徏 一个子q程或多个子q程时这个变量x是否复制C子进E的内存I间呢?不会的,子进E和父进E用同一个内存空间的变量Q但当子q程或父q程要改变变量x 的值时׃复制该变量,从而导致父子进E里的变量g同?strong style="word-wrap: break-word; ">父子q程变量是互不媄响的Q由于父子进E地址I间是完全隔开的,变量的地址可以是完全相同的?/p>
Linux?#8221;U程”?#8221;q程”实际上处于一个调度层ơ,׃n一个进E标识符I间Q这U限制得不可能在Linux上实现完全意义上的POSIXU程?Ӟ因此众多的LinuxU程库实现尝试都只能可能实现POSIX的绝大部分语义,q在功能上尽可能D。Linuxq程的创建是非常q速的。内核设?与实C书中甚至指出Linux创徏q程的速度和其他针对线E优化的操作pȝQWindows,SolarisQ创建线E的速度相比Q测试结果非常的好, 也就是说创徏速度很快。由于异步信h内核以进Eؓ单位分发的,而LinuxThreads的每个线E对内核来说都是一个进E,且没有实?#8221;U程l?#8221;Q因 此,某些语义不符合POSIX标准Q比如没有实现向q程中所有线E发送信PREADMEҎ作了说明。LinuxThreads中的U程同步很大E度?是徏立在信号基础上的Q这U通过内核复杂的信号处理机制的同步方式Q效率一直是个问题。LinuxThreads 的问题,特别是兼Ҏ上的问题,严重ȝ了Linux上的跨^台应用(如ApacheQ采用多U程设计Q从而得Linux上的U程应用一直保持在比较?的水q뀂在LinuxC中,已经有很多h在ؓ改进U程性能而努力,其中既包括用LU程库,也包括核心和用L配合改进的线E库。目前最Zh看好的有 两个目Q一个是RedHat公司牵头研发的NPTLQNative Posix Thread LibraryQ,另一个则是IBM投资开发的NGPTQNext Generation Posix ThreadingQ,二者都是围l完全兼容POSIX 1003.1cQ同时在核内和核外做工作以而实现多对多U程模型。这两种模型都在一定程度上弥补了LinuxThreads的缺点,且都是重L灶全新设 计的?/p>
lg所q的l论是在Linux下编E多用多q程~程用多线E编E?/strong>?/p> IBM有个家伙做了个测试,发现切换U程context的时候,windows比linux快一倍多。进出最快的锁(windows2k?critical section和linux的pthread_mutexQ,windows比linux的要快五倍左叟뀂当然这q不是说linux不好Q而且在经q实?~程之后Q综合来看我觉得linux更适合做high performance serverQ不q在多线E这个具体的领域内,linuxq是E逊windows一炏V这应该是情有可原的Q毕竟unix家族都是从多q程q来的,?windows从头是多线E的?/p> 如果是UNIX/linux环境Q采用多U程没必要?/p> 多线E比多进E性能高?误导Q?/p> 应该_多线E比多进E成本低Q但性能更低?/p> 在UNIX环境Q多q程调度开销比多U程调度开销Q没有显著区别,是_UNIXq程调度效率是很高的。内存消耗方面,二者只差全局数据区,现在内存都很便宜Q服务器内存动辄若干GQ根本不是问题?/p> 多进E是立体交通系l,虽然造h高,上坡下坡多耗点油,但是不堵车?/strong> 多线E是q面交通系l,造h低,但红l灯太多Q老堵车?/strong> 我们现在都开跑RQaQ主频)有的是,不怕上坡下坡,怕堵车?/p>高性能交易服务器中间gQ如TUXEDOQ都是主张多q程的。实际测试表明,TUXEDO性能和ƈ发效率是非常高的。TUXEDO是贝实验室的,与UNIX同宗Q应该是对UNIX理解最为深ȝQ他们的意见应该h很大的参考意?/span> 关于那个critical section和pthread_mutex_tQcritical section本质上是一个自旋锁Q短期锁当然快,要比也该是和pthread_spinlock_t比?/p> mutex和critical section的确是不能比的。一个涉及到内核Q一个没有涉及到内核?/p>
注:
转自http://www.soft-bin.com/html/2010/07/09/%E5%A4%9A%E8%BF%9B%E7%A8%8Bvs%E5%A4%9A%E7%BA%BF%E7%A8%8B%EF%BC%8C%E4%B8%80%E4%B8%AA%E9%95%BF%E6%9C%9F%E7%9A%84%E4%BA%89%E8%AE%BA.htmlQ貌g也是转别人的?/span>
转自:http://blog.chinaunix.net/uid-20556054-id-3068371.html
]]>
要改q?LinuxThreadsQ非常明显我们需要内核的支持Qƈ且需要重写线E库。有两个怺竞争的项目开始来满q些要求。一个包?IBM 的开发h员的团队开展了 NGPTQNext-Generation POSIX ThreadsQ项目。同ӞRed Hat 的一些开发h员开展了 NPTL 目。NGPT ?2003 q中期被攑ּ了,把这个领域完全留l了 NPTL?/p>
管?LinuxThreads ?NPTL 看v来似乎是一个必然的q程Q但是如果您正在Z个历史悠久的 Linux 发行版维护一些应用程序,q且计划很快pq行升Q那么如何迁Ud NPTL 上就会变成整个移植过E中重要的一个部分。另外,我们可能会希望了解二者之间的区别Q这样就可以对自q应用E序q行设计Q其能够更好地利用q两U技 术?/p>
本文详细介绍了这些线E模型分别是在哪些发行版上实现的?/p>
U程 应用程序划分成一个或多个同时q行的Q务。线E与传统的多dq程 之间的区别在于:U程׃n的是单个q程的状态信息,q会直接׃n内存和其他资源。同一个进E中U程之间的上下文切换通常要比q程之间的上下文切换速度?快。因此,多线E程序的优点是它可以比多进E应用程序的执行速度更快。另外,使用U程我们可以实现q行处理。这些相对于Zq程的方法所h的优Ҏ??LinuxThreads 的实现?/p>
LinuxThreads 最初的设计怿相关q程之间的上下文切换速度很快Q因此每个内核线E以处理很多相关的用户U线E。这导致了一对一 U程模型的革命?/p>
让我们来回顾一?LinuxThreads 设计l节的一些基本理念:
LinuxThreads 非常出名的一个特性就?em style="word-wrap: break-word; ">理U程Qmanager threadQ?/em>。管理线E可以满以下要求:
LinuxThreads 的设计通常都可以很好地工作Q但是在压力很大的应用程序中Q它的性能、可伸羃性和可用性都会存在问题。下面让我们来看一?LinuxThreads 设计的一些局限性:
NPTLQ或UCؓ Native POSIX Thread LibraryQ是 Linux U程的一个新实现Q它克服?LinuxThreads 的缺点,同时也符?POSIX 的需求。与 LinuxThreads 相比Q它在性能和稳定性方面都提供了重大的改进。与 LinuxThreads 一PNPTL 也实C一对一的模型?/p>
Ulrich Drepper ?Ingo Molnar ?Red Hat 参与 NPTL 设计的两名员工。他们的M设计目标如下Q?/p>
?LinuxThreads 相比QNPTL h很多优点Q?/p>
正如上面介绍的一PABI 的引入得可以同时支?NPTL ?LinuxThreads 模型。基本上来说Q这是通过 ld Q一个动态链接器/加蝲器)来进行处理的Q它会决定动态链接到哪个q行时线E库上?/p>
举例来说Q下面是 WebSphere® Application Server 对这个变量所使用的一些通用讄Q您可以Ҏ自己的需要进行适当的设|:
我们可以使用下面的命令来讄q个变量Q?/p>
export LD_ASSUME_KERNEL=2.4.19
注意Q对于Q?LD_ASSUME_KERNEL 讄的支持都取决于目前所支持的线E库?ABI 版本。例如,如果U程库ƈ不支?2.2.5 版本?ABIQ那么用户就不能?LD_ASSUME_KERNEL 讄?2.2.5。通常QNPTL 需?2.4.20Q?LinuxThreads 则需?2.4.1?/p>
如果您正q行的是一个启用了 NPTL ?Linux 发行版,但是应用E序却是Z LinuxThreads 模型来设计的Q那么所有这些设|通常都可以用?/p>
大部分现?Linux 发行版都预装?LinuxThreads ?NPTLQ因此它们提供了一U机制来在二者之间进行切换。要查看您的pȝ上正在用的是哪个线E库Q请q行下面的命令:
$ getconf GNU_LIBPTHREAD_VERSION
q会产生cM于下面的输出l果Q?/p>
NPTL 0.34
或者:
linuxthreads-0.10
Linux 发行版所使用的线E模型、glibc 版本和内核版?/a>
?1 列出了一些流行的 Linux 发行版,以及它们所采用的线E实现的cd、glibc 库和内核版本?/p>
U程实现 | C ?/th> | 发行?/th> | 内核 |
---|---|---|---|
LinuxThreads 0.7, 0.71 (for libc5) | libc 5.x | Red Hat 4.2 | |
LinuxThreads 0.7, 0.71 (for glibc 2) | glibc 2.0.x | Red Hat 5.x | |
LinuxThreads 0.8 | glibc 2.1.1 | Red Hat 6.0 | |
LinuxThreads 0.8 | glibc 2.1.2 | Red Hat 6.1 and 6.2 | |
LinuxThreads 0.9 | Red Hat 7.2 | 2.4.7 | |
LinuxThreads 0.9 | glibc 2.2.4 | Red Hat 2.1 AS | 2.4.9 |
LinuxThreads 0.10 | glibc 2.2.93 | Red Hat 8.0 | 2.4.18 |
NPTL 0.6 | glibc 2.3 | Red Hat 9.0 | 2.4.20 |
NPTL 0.61 | glibc 2.3.2 | Red Hat 3.0 EL | 2.4.21 |
NPTL 2.3.4 | glibc 2.3.4 | Red Hat 4.0 | 2.6.9 |
LinuxThreads 0.9 | glibc 2.2 | SUSE Linux Enterprise Server 7.1 | 2.4.18 |
LinuxThreads 0.9 | glibc 2.2.5 | SUSE Linux Enterprise Server 8 | 2.4.21 |
LinuxThreads 0.9 | glibc 2.2.5 | United Linux | 2.4.21 |
NPTL 2.3.5 | glibc 2.3.3 | SUSE Linux Enterprise Server 9 | 2.6.5 |
注意Q从 2.6.x 版本的内核和 glibc 2.3.3 开始,NPTL 所采用的版本号命名U定发生了变化:q个库现在是Ҏ所使用?glibc 的版本进行编L?/p>
Java™ 虚拟机(JVMQ的支持可能会稍有不同。IBM ?JVM 可以支持?1 ?glibc 版本高于 2.1 的大部分发行版?/p>
LinuxThreads 的限制已l在 NPTL 以及 LinuxThreads 后期的一些版本中得到了克服。例如,最新的 LinuxThreads 实现使用了线E注册来定位U程本地数据Q例如在 Intel® 处理器上Q它׃用了 %fs ?%gs D寄存器来定位访问线E本地数据所使用的虚拟地址。尽这个结果展CZ LinuxThreads 所采纳的一些修改的改进l果Q但是它在更高负载和压力试中,依然存在很多问题Q因为它q分C赖于一个管理线E,使用它来q行信号处理{操作?/p>
您应该记住,在?LinuxThreads 构徏库时Q需要?-D_REENTRANT ~译时标志。这使得库线E是安全的?/p>
最后,也许是最重要的事情,误?LinuxThreads 目的创已l不再积极更新它了,他们认ؓ NPTL 会取?LinuxThreads?/p>
LinuxThreads 的缺点ƈ不意味着 NPTL 没有错误。作Z个面?SMP 的设计,NPTL 也有一些缺炏V我曄看到q在最q的 Red Hat 内核上出现过q样的问题:一个简单线E在单处理器的机器上q行良好Q但?SMP 机器上却挂v了。我怿?Linux 上还有更多工作要做才能它具有更好的可~性,从而满高端应用程序的需求?/p>
学习
获得产品和技?/strong>
讨论
Vikram Shukla h 6 q用面向对象语aq行开发和设计的经验,目前是位于印?Banglore ?IBM Java Technology Center 的一名资pY件工E师Q负责对 IBM JVM on Linux q行支持?br />
转自:http://blog.chinaunix.net/uid-20556054-id-3068081.html
Native POSIX Thread LibraryQ?strong style="word-wrap: break-word; ">NPTLQ是一个能够使用POSIX Threads~写的程序在Linux内核上更有效地运行的软g?/p>
试表明QNPTL能够成功地在IA-32q_上在两秒U内生成100,000个线E;相应的没?span style="word-wrap: break-word; line-height: 1.5; ">NPTL的内核将耗费15分钟左右?/p>历史
?span style="word-wrap: break-word; line-height: 1.5; ">Linux内核2.6出现之前q程?最?可调度的对象Q当时的Linux不真正支持线E。但?span style="word-wrap: break-word; line-height: 1.5; ">Linux内核有一个系l调用指?span style="word-wrap: break-word; line-height: 1.5; ">clone()Q这个指令生一个呼叫调用的q程的复Ӟ而且q个复g与原q程使用同一地址I间?span style="word-wrap: break-word; line-height: 1.5; ">LinuxThreads计划使用q个pȝ调用来提供一个内核的线E支持。但是这个解x法与真正?span style="word-wrap: break-word; line-height: 1.5; ">POSIX标准有一些不相容的地方,其是在信号处理、进E调度和q程间同步原语方面?/p>
要提?span style="word-wrap: break-word; line-height: 1.5; ">LinuxThreads的效应很明显需要提供内核支持以及必重写线E函式库。ؓ了解册个问题出C两个互相竞争的项目:一?span style="word-wrap: break-word; line-height: 1.5; ">IBM的组的项目叫?span style="word-wrap: break-word; line-height: 1.5; ">NGPTQ?span style="word-wrap: break-word; line-height: 1.5; ">Next Generation POSIX ThreadsQ下一?span style="word-wrap: break-word; line-height: 1.5; ">POSIXU程Q,另一个组是由Red HatE序员组成的?003q中NGPT被放弃,几乎与此同时NPTL公布了?/p>
NPTL首次是随Red Hat Linux 9发表的。此前老式?span style="word-wrap: break-word; line-height: 1.5; ">Linux POSIXU程偶尔会发生系l无法生线E的毛病Q这个毛病的原因是因为在新线E开始的时候系l没有借机先占。当时的Windowspȝ对这个问题的解决比较好?span style="word-wrap: break-word; line-height: 1.5; ">Red Hat在关?span style="word-wrap: break-word; line-height: 1.5; ">Red Hat Linux 9上的Java的网上发表了一文章称NPTL解决了这个问题?/p>
从第3版开?span style="word-wrap: break-word; line-height: 1.5; ">NPTL?span style="word-wrap: break-word; line-height: 1.5; ">Red Hat Enterprise Linux的一部分Q从Linux内核2.6开始它被纳入内核。目前它完全被结合入GNU C 函式库?/p>设计
NPTL的解x法与LinuxThreadscMQ内核看到的首要抽象依然是一个进E,新线E是通过clone()pȝ调用产生的。但?span style="word-wrap: break-word; line-height: 1.5; ">NPTL需要特D的内核支持来解军_步的原始cd之间互相竞争的状c在q种情况下线E必能够入眠和再复苏。用来完成这个Q务的原始cd叫做futex?/p>
NPTL是一个所谓的1×1U程函式库。用户生的U程与内核能够分配的物g之间的联pL一对一的。这是所有线E程式中最单的?/p>
转自http://zh.wikipedia.org/wiki/Native_POSIX_Thread_Library#cite_note-1
转自Q?a style="line-height: 1.5; font-size: 12px; ">http://blog.chinaunix.net/uid-20556054-id-3068071.html
l度 | 多进E?/span> | 多线E?/span> | ȝ |
数据׃n、同?/span> | 数据是分开?׃n复杂Q需要用IPC;同步?/span> | 多线E共享进E数据:׃n单;同步复杂 | 各有优势 |
内存、CPU | 占用内存多,切换复杂QCPU利用率低 | 占用内存,切换单,CPU利用率高 | U程占优 |
创徏销毁、切?/span> | 创徏销毁、切换复杂,速度?nbsp; | 创徏销毁、切换简单,速度?nbsp; | U程占优 |
~程调试 | ~程单,调试?/span> | ~程复杂Q调试复?/span> | q程占优 |
可靠?/span> | q程间不会相互媄?nbsp; | 一个线E挂掉将D整个q程挂掉 | q程占优 |
分布?nbsp; | 适应于多核、多机分?Q如果一台机器不够,扩展到多台机器比较简?br style="word-wrap: break-word; " /> | 适应于多核分?/span> | q程占优 |
U程是独立调度和分派的基本单位。线E可以操作系l内核调度的内核U程Q如Win32 U程Q由用户q程自行调度的用LE,如Linux Portable ThreadQ?或者由内核与用戯E,如Windows 7的线E,q行混合调度?/p>
同一q程中的多条U程共享该q程中的全部pȝ资源Q如虚拟地址I间Q文件描q符和信号处理等{。但同一q程中的多个U程有各自的调用?call stack)Q自q寄存器环境(register context)Q自qU程本地存储(thread-local storage)?/p>
一个进E可以有很多U程Q每条线Eƈ行执行不同的d?/p>
在多核或多CPUQ或支持Hyper-threading的CPU上用多U程E序设计的好处是显而易见,x高了E序的执行吞吐率。在单CPU单核的计机上,使用多线E技术,也可以把q程中负责IO处理、hZ互而常备阻塞的部分与密集计的部分分开来执行,~写专门的workhorseU程执行密集计算Q从而提高了E序的执行效率。(摘自Qhttp://zh.wikipedia.org/wiki/U程Q?strong style="word-wrap: break-word; ">
q程是资源分配的最单位,U程是CPU调度的最单?/strong>。线E和q程的区别在?子进E和父进E有不同的代码和数据I间,而多个线E则׃n数据I间,每个U程有自q执行堆栈和程序计数器为其执行上下?多线E主要是Z节约CPU旉,发挥利用,Ҏ具体情况而定. U程的运行中需要用计机的内存资源和CPU?br style="word-wrap: break-word; " />
多进E?/strong>Q?q程是程序在计算Z的一ơ执行活动。当你运行一个程序,你就启动了一个进E。显ӞE序是死?静态的)Q进E是zȝ(动态的)。进E可以分为系l进E和用户q程。凡是用于完成操作系l的各种功能的进E就是系l进E,它们是处于q行状态下的操作系l本w;所有由用户启动的进E都是用戯E。进E是操作pȝq行资源分配的单位?q程又被l化为线E,也就是一个进E下有多个能独立q行的更的单位。在同一个时间里Q同一个计机pȝ中如果允怸个或两个以上的进E处于运行状态,q便是多d。现代的操作pȝ几乎都是多Q务操作系l,能够同时理多个q程的运行?多Q务带来的好处是明昄Q比如你可以边听mp3边上|,与此同时甚至可以下载的文打印出来Q而这些Q务之间丝毫不会相互干扰。那么这里就涉及到ƈ行的问题Q俗话说Q一心不能二用,q对计算Z一P原则上一个CPU只能分配l一个进E,以便q行q个q程。我们通常使用的计机中只有一个CPUQ也是说只有一颗心Q要让它一心多用,同时q行多个q程Q就必须使用q发技术。实现ƈ发技术相当复杂,最Ҏ理解的是“旉片轮转进E调度算?#8221;Q它的思想单介l如下:在操作系l的理下,所有正在运行的q程轮流使用CPUQ每个进E允许占用CPU的时间非常短(比如10毫秒)Q这Lh本感觉不出来 CPU是在轮流为多个进E服务,好象所有的q程都在不间断地q行一栗但实际上在M一个时间内有且仅有一个进E占有CPU?如果一台计机有多个CPUQ情况就不同了,如果q程数小于CPU敎ͼ则不同的q程可以分配l不同的CPU来运行,q样Q多个进E就是真正同时运行的Q这便是q行。但如果q程数大于CPU敎ͼ则仍焉要用ƈ发技术?q行CPU分配是以U程为单位的Q一个进E可能由多个U程l成Q这时情冉|加复杂,但简单地_有如下关p:
ȝE数<= CPU数量Qƈ行运?nbsp;
ȝE数> CPU数量Qƈ发运?nbsp;
q行q行的效率显焉于ƈ发运行,所以在多CPU的计机中,多Q务的效率比较高。但是,如果在多CPU计算Z只运行一个进E?U程)Q就不能发挥多CPU的优ѝ?q里涉及到多d操作pȝ的问题,多Q务操作系l?如Windows)的基本原理是:操作pȝCPU的时间片分配l多个线E?每个U程在操作系l指定的旉片内完成(注意,q里的多个线E是分属于不同进E的).操作pȝ不断的从一个线E的执行切换到另一个线E的执行,如此往?宏观上看?好像是多个U程在一h?׃q多个线E分属于不同的进E?因此在我们看?好像是多个q程在同时执?q样实C多Q?Q摘自:http://zhidao.baidu.com/question/2601473Q?/p> q程间通信Q?strong style="word-wrap: break-word; ">IPC
多线E?/strong>Q在计算机编E中Q一个基本的概念是同时对多个Q务加以控制。许多程序设计问题都要求E序能够停下手头的工作,改ؓ处理其他一些问题,再返回主q程。可以通过多种途径辑ֈq个目的。最开始的时候,那些掌握机器低语言的程序员~写一?#8220;中断服务例程”Q主q程的暂停是通过gU的中断实现的。尽这是一U有用的ҎQ但~出的程序很隄植,由此造成了另一cȝ代h高昂问题。中断对那些实时性很强的d来说是很有必要的。但对于其他许多问题Q只要求问题划分进入独立运行的E序片断中,使整个程序能更迅速地响应用户的请求。
最开始,U程只是用于分配单个处理器的处理旉的一U工兗但假如操作pȝ本n支持多个处理器,那么每个U程都可分配l一个不同的处理器,真正q入“q行q算”状态。从E序设计语言的角度看Q多U程操作最有h值的Ҏ之一是E序员不必关心到底用了多少个处理器。程序在逻辑意义上被分割为数个线E;假如机器本n安装了多个处理器Q那么程序会q行得更快,毋需作出MҎ的调校。根据前面的Q大家可能感觉线E处理非常简单。但必须注意一个问题:׃n资源Q如果有多个U程同时q行Q而且它们试图讉K相同的资源,׃遇到一个问题。D个例子来_两个U程不能信息同时发送给一台打印机。ؓ解决q个问题Q对那些可共享的资源来说Q比如打印机Q,它们在用期间必进入锁定状态。所以一个线E可资源锁定,在完成了它的d后,再解开Q释放)q个锁,使其他线E可以接着使用同样的资源。
多线E是Z同步完成多项dQ不是ؓ了提高运行效率,而是Z提高资源使用效率来提高系l的效率。线E是在同一旉需要完成多Q务的时候实现的?br style="word-wrap: break-word; " />一个采用了多线E技术的应用E序可以更好地利用系l资源。其主要优势在于充分利用了CPU的空闲时间片Q可以用可能少的时间来对用L要求做出响应Q得进E的整体q行效率得到较大提高Q同时增Z应用E序的灵zL。更为重要的是,׃同一q程的所有线E是׃n同一内存Q所以不需要特D的数据传送机Ӟ不需要徏立共享存储区或共享文Ӟ从而得不同Q务之间的协调操作与运行、数据的交互、资源的分配{问题更加易于解冻I摘自Qhttp://baike.baidu.com/view/65706.htmQ?br style="word-wrap: break-word; " />通常由操作系l负责多个线E的调度和执行?br style="word-wrap: break-word; font-family: 宋体, Arial; font-size: 12px; line-height: 15px; background-color: #f5f7f8; " />
q程间通信技术包括消息传递、同步、共享内存和q程q程调用。IPC是一U标准的Unix通信机制?/span>
使用IPC 的理由:
主要?span style="word-wrap: break-word; line-height: 1.5; "> IPC Ҏ
Ҏ | 提供方(操作pȝ或其他环境) |
文g | 多数操作pȝ |
信号 | 多数操作pȝ |
Socket | 多数操作pȝ |
消息队列(en:Message queue) | 多数操作pȝ |
道(en:Pipe) | 所有的 POSIX systems, Windows. |
具名道(en:Named Pipe) | 所有的 POSIX pȝ, Windows. |
信号?/span>(en:Semaphore) | 所有的 POSIX pȝ, Windows. |
׃n内存 | 所有的 POSIX pȝ, Windows. |
Message passing(en:Message passing) | 用于 MPI规范Q?span style="word-wrap: break-word; line-height: 1.5; ">Java RMI, CORBA, MSMQ, MailSlot以及其他. |
Memory-mapped file(en:Memory-mapped file) | 所有的 POSIX pȝ, Windows. |