??xml version="1.0" encoding="utf-8" standalone="yes"?>久久Av无码精品人妻系列,久久国产劲爆AV内射—百度,久久综合九色综合网站http://m.shnenglu.com/mysileng/archive/2012/12/18/196408.html鑫龙鑫龙Tue, 18 Dec 2012 05:57:00 GMThttp://m.shnenglu.com/mysileng/archive/2012/12/18/196408.htmlhttp://m.shnenglu.com/mysileng/comments/196408.htmlhttp://m.shnenglu.com/mysileng/archive/2012/12/18/196408.html#Feedback0http://m.shnenglu.com/mysileng/comments/commentRss/196408.htmlhttp://m.shnenglu.com/mysileng/services/trackbacks/196408.html转自http://www.ibm.com/developerworks/cn/linux/kernel/l-thread/Q杨沙洲 (pubb@163.net)国防U技大学计算机学?a name="N10037" style="word-wrap: break-word; color: #63401b; ">Q? 

一.基础知识Q线E和q程

按照教科书上的定义,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>

?Linux 2.4内核中的轻量q程实现

最初的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>

?LinuxThread的线E机?/a>

LinuxThreads是目前Linuxq_上用最为广泛的U程库,由Xavier Leroy (Xavier.Leroy@inria.fr)负责开发完成,q已l定在GLIBC中发行。它所实现的就是基于核心轻量q程?一对一"U程模型Q一 个线E实体对应一个核心轻量q程Q而线E之间的理在核外函数库中实现?/p>

1.U程描述数据l构及实现限?/a>

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:


? __pthread_handles数组l构 

新创建的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>

2.理U程

"一对一"模型的好处之一是线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>
? 创徏理U程的流E? src= 

初始化结束后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>

3.U程?/a>

在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间的功能分配如?图:


? 栈结构示? src= 

低地址被保护的面用来监测栈溢出?/p>

对于用户指定的栈Q在按照指针对界后,讄U程栈顶Qƈ计算出栈底,不做保护Q正性由用户自己保证?/p>

不论哪种l织方式Q线E描q结构L位于栈顶紧邻堆栈的位|?/p>

4.U程id和进Eid

每个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>

5.U程的创?/a>

在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>

6.LinuxThreads的不?/a>

׃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>

?其他的线E实现机?/a>

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



鑫龙 2012-12-18 13:57 发表评论
]]>
多进E与多线E(七)--多线E效??http://m.shnenglu.com/mysileng/archive/2012/12/18/196407.html鑫龙鑫龙Tue, 18 Dec 2012 05:56:00 GMThttp://m.shnenglu.com/mysileng/archive/2012/12/18/196407.htmlhttp://m.shnenglu.com/mysileng/comments/196407.htmlhttp://m.shnenglu.com/mysileng/archive/2012/12/18/196407.html#Feedback0http://m.shnenglu.com/mysileng/comments/commentRss/196407.htmlhttp://m.shnenglu.com/mysileng/services/trackbacks/196407.html阅读全文

鑫龙 2012-12-18 13:56 发表评论
]]>
多进E与多线E(六)--LinuxThreads(?http://m.shnenglu.com/mysileng/archive/2012/12/18/196406.html鑫龙鑫龙Tue, 18 Dec 2012 05:55:00 GMThttp://m.shnenglu.com/mysileng/archive/2012/12/18/196406.htmlhttp://m.shnenglu.com/mysileng/comments/196406.htmlhttp://m.shnenglu.com/mysileng/archive/2012/12/18/196406.html#Feedback0http://m.shnenglu.com/mysileng/comments/commentRss/196406.htmlhttp://m.shnenglu.com/mysileng/services/trackbacks/196406.htmlQ注Q这文章{自网l,虽然Linux从内?.6开始,多线E已使用NPTL技术,但是q篇文章Ҏ们理解多U程技术还是挺有用的)

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

鑫龙 2012-12-18 13:55 发表评论
]]>多进E与多线E(五)--Linux U程模型的比较:LinuxThreads ?NPTL(?http://m.shnenglu.com/mysileng/archive/2012/12/18/196405.html鑫龙鑫龙Tue, 18 Dec 2012 05:52:00 GMThttp://m.shnenglu.com/mysileng/archive/2012/12/18/196405.htmlhttp://m.shnenglu.com/mysileng/comments/196405.htmlhttp://m.shnenglu.com/mysileng/archive/2012/12/18/196405.html#Feedback0http://m.shnenglu.com/mysileng/comments/commentRss/196405.htmlhttp://m.shnenglu.com/mysileng/services/trackbacks/196405.html?Linux 最初开发时Q在内核中ƈ不能真正支持U程。但是它的确可以通过 clone() pȝ调用进E作为可调度的实体。这个调用创Z调用q程Qcalling processQ的一个拷贝,q个拯与调用进E共享相同的地址I间。LinuxThreads 目使用q个调用来完全在用户I间模拟对线E的支持。不q的是,q种Ҏ有一些缺点,其是在信号处理、调度和q程间同步原语方面都存在问题。另外,q个 U程模型也不W合 POSIX 的要求?/p>

要改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>

LinuxThreads 设计l节

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可以满以下要求:

    • pȝ必须能够响应l止信号q杀L个进E?/li>
    • 以堆栈Ş式用的内存回收必须在线E完成之后进行。因此,U程无法自行完成q个q程?/li>
    • l止U程必须q行{待Q这样它们才不会q入僵尸状态?/li>
    • U程本地数据的回攉要对所有线E进行遍历;q必ȝ理U程来进行?/li>
    • 如果ȝE需要调?pthread_exit()Q那么这个线E就无法l束。主U程要进入睡眠状态,而管理线E的工作是在所有线E都被杀M后来唤醒q个ȝE?/li>

  • Zl护U程本地数据和内存,LinuxThreads 使用了进E地址I间的高位内存(在堆栈地址之下Q?br style="word-wrap: break-word; " />
  • 原语的同步是使用信号 来实现的。例如,U程会一直阻塞,直到被信号唤醒ؓ止?br style="word-wrap: break-word; " />
  • 在克隆系l的最初设计之下,LinuxThreads 每个线E都是作Z个具有惟一q程 ID 的进E实现的?br style="word-wrap: break-word; " />
  • l止信号可以杀L有的U程。LinuxThreads 接收到终止信号之后,理U程׃使用相同的信hL有其他线E(q程Q?br style="word-wrap: break-word; " />
  • Ҏ LinuxThreads 的设计,如果一个异步信可发送了Q那么管理线E就会将q个信号发送给一个线E。如果这个线E现在阻塞了q个信号Q那么这个信号也׃被挂赗这是因为管理线E无法将q个信号发送给q程Q相反,每个U程都是作ؓ一个进E在执行?br style="word-wrap: break-word; " />
  • U程之间的调度是由内核调度器来处理的?/li>

LinuxThreads 及其局限?/a>

LinuxThreads 的设计通常都可以很好地工作Q但是在压力很大的应用程序中Q它的性能、可伸羃性和可用性都会存在问题。下面让我们来看一?LinuxThreads 设计的一些局限性:

关于 NPTL

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>

  • q个新线E库应该兼容 POSIX 标准?br style="word-wrap: break-word; " />
  • q个U程实现应该在具有很多处理器的系l上也能很好地工作?br style="word-wrap: break-word; " />
  • Z段d创徏新线E应该具有很低的启动成本?br style="word-wrap: break-word; " />
  • NPTL U程库应该与 LinuxThreads 是二q制兼容的。注意,为此我们可以使用 LD_ASSUME_KERNELQ这会在本文E后q行讨论?br style="word-wrap: break-word; " />
  • q个新线E库应该可以利用 NUMA 支持的优炏V?/li>

NPTL 的优?/a>

?LinuxThreads 相比QNPTL h很多优点Q?/p>

LD_ASSUME_KERNEL 环境变量

正如上面介绍的一PABI 的引入得可以同时支?NPTL ?LinuxThreads 模型。基本上来说Q这是通过 ld Q一个动态链接器/加蝲器)来进行处理的Q它会决定动态链接到哪个q行时线E库上?/p>

举例来说Q下面是 WebSphere® Application Server 对这个变量所使用的一些通用讄Q您可以Ҏ自己的需要进行适当的设|:

  • LD_ASSUME_KERNEL=2.4.19Q这会覆?NPTL 的实现。这U实现通常都表CZ用标准的 LinuxThreads 模型Qƈ启用动堆栈的特性?/li>
  • LD_ASSUME_KERNEL=2.2.5Q这会覆?NPTL 的实现。这U实现通常都表CZ?LinuxThreads 模型Q同时用固定堆栈大?/li>

我们可以使用下面的命令来讄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>

GNU_LIBPTHREAD_VERSION ?/a>

大部分现?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>
?1. Linux 发行版及其线E实?/em>
U程实现C ?/th>发行?/th>内核
LinuxThreads 0.7, 0.71 (for libc5)libc 5.xRed Hat 4.2
LinuxThreads 0.7, 0.71 (for glibc 2)glibc 2.0.xRed Hat 5.x
LinuxThreads 0.8glibc 2.1.1Red Hat 6.0
LinuxThreads 0.8glibc 2.1.2Red Hat 6.1 and 6.2
LinuxThreads 0.9
Red Hat 7.22.4.7
LinuxThreads 0.9glibc 2.2.4Red Hat 2.1 AS2.4.9
LinuxThreads 0.10glibc 2.2.93Red Hat 8.02.4.18
NPTL 0.6glibc 2.3Red Hat 9.02.4.20
NPTL 0.61glibc 2.3.2Red Hat 3.0 EL2.4.21
NPTL 2.3.4glibc 2.3.4Red Hat 4.02.6.9
LinuxThreads 0.9glibc 2.2SUSE Linux Enterprise Server 7.12.4.18
LinuxThreads 0.9glibc 2.2.5SUSE Linux Enterprise Server 82.4.21
LinuxThreads 0.9glibc 2.2.5United Linux2.4.21
NPTL 2.3.5glibc 2.3.3SUSE Linux Enterprise Server 92.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>

l束?/a>

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>

参考资?/a>

学习

获得产品和技?/strong>

讨论

关于作?/a>

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



鑫龙 2012-12-18 13:52 发表评论
]]>
多进E与多线E(四)--NPTL(?http://m.shnenglu.com/mysileng/archive/2012/12/18/196404.html鑫龙鑫龙Tue, 18 Dec 2012 05:50:00 GMThttp://m.shnenglu.com/mysileng/archive/2012/12/18/196404.htmlhttp://m.shnenglu.com/mysileng/comments/196404.htmlhttp://m.shnenglu.com/mysileng/archive/2012/12/18/196404.html#Feedback0http://m.shnenglu.com/mysileng/comments/commentRss/196404.htmlhttp://m.shnenglu.com/mysileng/services/trackbacks/196404.htmlNative POSIX Thread Library

l基癄Q自q癄全书

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



鑫龙 2012-12-18 13:50 发表评论
]]>多进E与多线E(三)--多进E?or 多线E??http://m.shnenglu.com/mysileng/archive/2012/12/18/196403.html鑫龙鑫龙Tue, 18 Dec 2012 05:49:00 GMThttp://m.shnenglu.com/mysileng/archive/2012/12/18/196403.htmlhttp://m.shnenglu.com/mysileng/comments/196403.htmlhttp://m.shnenglu.com/mysileng/archive/2012/12/18/196403.html#Feedback0http://m.shnenglu.com/mysileng/comments/commentRss/196403.htmlhttp://m.shnenglu.com/mysileng/services/trackbacks/196403.html阅读全文

鑫龙 2012-12-18 13:49 发表评论
]]>
多进E与多线E(二)--g熊掌(?http://m.shnenglu.com/mysileng/archive/2012/12/18/196402.html鑫龙鑫龙Tue, 18 Dec 2012 05:47:00 GMThttp://m.shnenglu.com/mysileng/archive/2012/12/18/196402.htmlhttp://m.shnenglu.com/mysileng/comments/196402.htmlhttp://m.shnenglu.com/mysileng/archive/2012/12/18/196402.html#Feedback0http://m.shnenglu.com/mysileng/comments/commentRss/196402.htmlhttp://m.shnenglu.com/mysileng/services/trackbacks/196402.html关于多进E和多线E,教科书上最l典的一句话?#8220;q程是资源分配的最单位,U程是CPU调度的最单?#8221;。这句话应付考试基本上够了,但如果在工作中遇到类似的选择问题Q那没有那么简单了Q选的不好Q会让你深受其害?br style="word-wrap: break-word; " />l常在网l上看到有XDJM?#8220;多进E好q是多线E好Q?#8221;?Linux下用多进E还是多U程Q?{等期望一x逸的问题Q只能说Q没有最好,只有更好Q根据实际情冉|判断Q哪个更加合适就是哪个好?br style="word-wrap: break-word; " />我们按照多个不同的维度,来看看多q程和多U程的对比(注:因ؓ是感性的比较Q因此都是相对的Q不是说一个好得不得了Q另一个差的无法忍受)

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程占优



1)需要频J创建销毁的优先用线E?/span>
   实例Qweb服务器。来一个徏立一个线E,断了销毁线E。要是用q程Q创建和销毁的代h是很难承受的?/span>
2Q需要进行大量计的优先使用U程?/span>
   所谓大量计,当然是要消耗很多cpuQ切换频J了Q这U情况先U程是最合适的?/span>
   实例Q图像处理、算法处?/span>
3Q强相关的处理用U程Q若相关的处理用q程?/span>
   什么叫强相兟뀁弱相关Q理Z很难定义Q给个简单的例子明白了?/span>
   一般的server需要完成如下Q务:消息收发和消息处理。消息收发和消息处理是q关的dQ而消息处理里面可能又分ؓ消息解码、业务处理,q两个Q务相Ҏ说相x就要强多了。因此消息收发和消息处理可以分进E设计,消息解码和业务处理可以分U程设计?/span>
4Q可能扩展到多机分布的用q程Q多核分布的用线E?/span>
5Q都满需求的情况下,用你最熟悉、最拿手的方式?/span>
   至于”数据׃n、同?#8220;?#8220;~程、调?#8221;?#8220;可靠?#8221;q几个维度的所谓的“复杂、简?#8221;应该怎么取舍Q只能说Q没有明的选择Ҏ。一般有一个选择原则Q如果多q程和多U程都能够满求,那么选择你最熟悉、最拿手的那个?/span>
需要提醒的是:虽然有这么多的选择原则Q但实际应用中都?#8220;q程+U程”的结合方式,千万不要真的陷入一U非此即彼的误区?/span>

转自Qhttp://software.intel.com/zh-cn/blogs/2010/07/20/400004478/ 

转自:http://blog.chinaunix.net/uid-20556054-id-3061450.html

鑫龙 2012-12-18 13:47 发表评论
]]>
多进E与多线E(一Q?-基本概念(?http://m.shnenglu.com/mysileng/archive/2012/12/18/196401.html鑫龙鑫龙Tue, 18 Dec 2012 05:44:00 GMThttp://m.shnenglu.com/mysileng/archive/2012/12/18/196401.htmlhttp://m.shnenglu.com/mysileng/comments/196401.htmlhttp://m.shnenglu.com/mysileng/archive/2012/12/18/196401.html#Feedback0http://m.shnenglu.com/mysileng/comments/commentRss/196401.htmlhttp://m.shnenglu.com/mysileng/services/trackbacks/196401.htmlq程Q英语:ProcessQ中国大陆译?strong style="word-wrap: break-word; ">q程
Q台湾译?strong style="word-wrap: break-word; ">行程
Q?nbsp;是具有一定独立功能的E序关于某个数据集合上的一ơ运行活动,是系l进行资源分配和调度的一个独立单位?br style="word-wrap: break-word; " />E序是一l指令的有序集合Q它本n没有Mq行的含义,只是一个静态实体。进E是E序在某个数据集上的执行Q是一个动态实体(q程本n不会q行Q是U程的容器。)。它因创生,因调度而运行,因等待资源或事g而被处于{待状态,因完成Q务而被撤消Q反映了一个程序在一定的数据集上q行的全部动态过E?br style="word-wrap: break-word; " />若干q程有可能与同一个程序相关系Q且每个q程皆可以同步(循序Q或不同步(qQ的方式独立q行。进EؓC分时pȝ的基本运作单位?br style="word-wrap: break-word; " />

U程
Q英语:threadQ台湾译?strong style="word-wrap: break-word; ">q行l)Q?/strong>操作pȝ技术中的术语,?span style="word-wrap: break-word; line-height: 1.5; ">操作pȝ能够q行q算调度的最单位。它被包涵在q程之中Q一条线E指的是q程中一个单一序的控制流Q一个进E中可以q发多个U程Q每条线Eƈ行执行不同的d。在Unix System V及SunOS中也被称量进E(lightweight processesQ,但轻量进E更多指内核U程(kernel thread)Q而把用户U程(user thread)UCؓU程?/p>

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>
多线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?strong style="word-wrap: break-word; ">IPCQ?em style="word-wrap: break-word; ">Inter-Process CommunicationQ,指至两?span style="word-wrap: break-word; line-height: 1.5; ">q程?span style="word-wrap: break-word; line-height: 1.5; ">U程间传送数据或信号的一些技术或Ҏ。进E是计算机系l?/span>分配资源的最单位。每个进E都有自q一部分独立的系l资源,彼此是隔ȝ。ؓ了能使不同的q程互相讉K资源q进行协调工作,才有了进E间通信。这?span style="word-wrap: break-word; line-height: 1.5; ">q程可以q行在同一计算Z或网l连接的不同计算Z?/span>

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 , Windows.

信号?/span>(en:Semaphore)

所有的 POSIX , Windows.

׃n内存

所有的 POSIX , Windows.

Message passing(en:Message passing)
(
不共?span style="word-wrap: break-word; line-height: 1.5; ">)

用于 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 , Windows.

Q摘自:http://zh.wikipedia.org/wiki/行程間通訊Q?nbsp;

转自:http://blog.chinaunix.net/uid-20556054-id-3060696.html

鑫龙 2012-12-18 13:44 发表评论
]]>
޹ƷۺϾþ| þwww˳ɿƬ| þۺϳDž| þþƷŷպƷ| þ޾ƷAVӣ| 2020þþƷۺһ| þþҹƷ| þþþޱٸ| þ99Ʒþþþþ| þþܳ| ۺϾþһ | þۺϾɫۺŷȥ| Ļһþվ| þ޹ŷ޾Ʒһ| þseƷһƷ| Ʒþþþþù| ޾ƷþëƬ| ۺ˾þۺ| 97þۺɫۺɫhd| ݺݺɫۺϾþ| þ99Ʒ鶹| þþƷAVþþ| ĻþþƷ1 | Ʒ99þþþƷ| þ×Ʒþþþþ| þۺϾþۺϾþ| Ʒľþþþþþ| ƷۺϾþĻ| þþþ99ƷƬëƬ| ˾þü91| Ʒʾþþþ999Ұ| Ʒþþþþþþ| ľþۺĻ| þþùƷ| þþۺ| ĻۺϾþò| ޹Ʒ˾þ | ѾþþƷ99þ| þþþþҹƷƷ| ۺ˾þۺ| žžƷ99þþ㽶|