Linux的进程管理(一)

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

Linux进程控制2主要内容1.进程、线程和轻量级进程的概念2.进程描述符3.进程状态4.如何标识一个进程5.进程内核栈6.进程间的关系7.与进程创建相关的系统调用3进程、线程和轻量级进程1.进程是程序执行的一个实例,是有限状态机的一次迁移过程。2.进程和程序的区别:动态与静止;多对一3.进程是资源分配的实体,这些资源包括:PID、task_struct、独立的内存地址空间、打开的文件描述符、信号处理函数对应表、挂起的信号等。4.线程是进程内一个独立的执行线路,是CPU调度的实体。5.线程共享所属进程的资源,但也有私有资源:栈、CPU寄存器状态、CPU时间片、优先级、线程局部存储TLS6.在Linux下,线程是利用轻量级进程机制实现的。7.多个轻量级进程共享同一套资源(同一内存空间),但具有不同的栈和CPU寄存器状态。4进程描述符task_struct1.进程描述符与进程一一对应,记录了与进程相关的所有信息2.进程描述符一般较大,(32位机1.7KB)3.创建进程描述符时使用了SLAB分配器5进程描述符task_structLinux2.6进程的状态include/linux/sched.h2020/1/23Linux操作系统分析7/65进程状态转换图EXIT_ZOMBIE或者EXIT_DEAD或者TASK_DEAD如何标识一个进程使用进程描述符地址进程和进程描述符之间有非常严格的一一对应关系,使得用32位进程描述符地址标识进程非常方便使用PID(ProcessID,PID)每个进程的PID都存放在进程描述符的pid域中进程的PID进程的pid字段Pid最大值,参见kernel/pid.c顺序使用&&循环使用include/linux/types.hinclude/asm-XXX/posix_typesYYY.hinclude/linux/threads.h10如何获得一个空闲的PID1.32位机上,PID最大为327672.为了循环使用PID编号,内核定义了一个pidmap_array位图,pidmap_array包含32768个位,刚好放到一个页框中。3.alloc_pid是如何实现的?(last_pid变量)11如何由PID获得对应的进程描述符1.如何实现find_task_by_pid(nr)?2.pidhashtable(固定数组,一般占4个页框,2048个表项)12structpidstructpid_link{intnr;//pid的数值structhlist_nodepid_chain;structlist_headpid_list;}structtask_struct{…structpid_linkpids[4];…}13如何由PID获得对应的进程描述符14/65进程和进程的内核堆栈Linux为每个进程分配一个8KB大小的内存区域,用于存放该进程两个不同的数据结构:Thread_info进程的内核态堆栈进程处于内核态时使用,不同于用户态堆栈内核控制路径所用的堆栈很少,因此对栈和Thread_info来说,8KB足够了Thread_info15用户态到内核态的切换1.用户态和内核态的区别?2.从用户态切换到内核态的3种方式:•系统调用:int80或sysinter•中断•异常3.从用户态切换到内核态后:•进程上下文(主要指页表)不切换•CPU自动切换到当前进程对应的内核态堆栈工作•CPU自动将用户态的寄存器状态和返回地址存放到内核栈Thread_unionC语言允许用如下的一个union结构来方便的表示这样的一个混合体thread_info由体系结构相关部分定义阅读include/asm-x86/thread_info.h以及include/asm-x86/thread_info_32.hinclude/linux/sched.hCurrent宏的使用Current宏可以看成当前进程的进程描述符指针,在内核中直接使用举例:比如current-pid返回在CPU上正在执行的进程的PIDcurrent宏的实现:#defineget_current()(current_thread_info()-task)#definecurrentget_current()current_thread_info的汇编代码是:movl$-THREAD_SIZE,%eax;andl%esp,%eax其中#defineTHREAD_SIZE(2*PAGE_SIZE)内核栈thread_infotask_struct*taskvoid*stacktask_struct21进程间的关系1.父子关系:parent,real_parent,children2.兄弟关系:sibling3.线程组关系:tgid,group_leader,thread_group4.进程组关系:signal-pgrp5.会话组关系:signal-session6.被调试关系:ptrace_children,ptrace_list7.系统中所有进程的task_struct被串成一个双向循环链表22进程间的关系进程启动23手工启动前台启动:shell中输入命令:program后台启动:shell中输入命令:program&调度启动利用at命令在指定时刻启动利用cron命令定期启动进程管理相关命令2425在程序中创建与终止进程•进程的创建和执行:–Linux中进程的创建进程被分解到两个单独的函数中取执行:fork()和exec函数族。首先,fork()通过拷贝当前进程创建一个子进程,子进程与父进程的区别仅仅在于不同的PID、PPID和某些资源及统计量。exec函数族负责读取可执行文件并将其载入地址空间开始运行。•进程的终止:–进程终结也需要做很多繁琐的收尾工作,系统必须保证进程所占用的资源回收,并通知父进程。Linux首先把终止的进程设置为僵尸状态,这个时候,进程无法投入运行了,它的存在只为父进程提供信息,申请死亡。父进程得到信息后,开始调用wait函数族,最终赐死子进程,子进程占用的所有资源被全部释放。fork函数•fork()–fork()函数用于从已存在的进程中创建一个新进程。新进程称为子进程,而原进程称为父进程。–使用fork()函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空间,包括进程上下文、代码段、进程堆栈、内存信息、打开的文件描述符、信号控制设定、进程优先级、进程组号、当前工作目录、根目录、资源限制和控制终端等,而子进程所独有的只有它的进程号、资源使用和计时器等。•fork()函数语法:fork的另一个例子intmain(){intvar;pid_tpid;var=88;if((pid=fork())0){printf(forkerror\n);}elseif(pid==0){var++;}else{sleep(2);}printf(pid=%d,var=%d\n,getpid(),var);return0;}关于fork的两个问题连续调用3次fork,共可产生多少个进程?下面的程序一共输出多少个“-”?#includestdio.h#includesys/types.h#includeunistd.hintmain(void){inti;for(i=0;i2;i++){fork();printf(-);}return0;}子进程复制了父进程的哪些资源?•用户ID、用户组ID、进程组ID、会话ID•当前工作目录、根目录、环境变量•文件访问权限、资源访问权限•信号屏蔽位•打开的文件描述符•进程地址空间(数据段、代码段、堆栈段)•…Fork函数的应用逻辑—孙悟空逻辑intmain(){…….//遇到两个需要并行执行的任务:任务1和任务2pid=fork();//分身术if(pid==0){……//子进程处理任务1}else{……//父进程处理任务2}return0;}Fork函数应用例1intmain(){intfd1=open(“data_file1”,…);intfd2=open(“data_file2”,…);pid_tpid;if((pid=fork())==0){close(fd2);read(fd1,buffer,len);…//处理文件1的数据}else{close(fd1);read(fd2,buffer,len);…//处理文件2的数据}}Windows创建进程API—CreateProcessBOOLCreateProcess(LPCTSTRlpApplicationName,//新进程将要使用的可执行文件的名字(路径)LPTSTRlpCommandLine,//递给新进程的命令行字符串LPSECURITY_ATTRIBUTESlpProcessAttributes。LPSECURITY_ATTRIBUTESlpThreadAttributes,BOOLbInheritHandles,DWORDdwCreationFlags,LPVOIDlpEnvironment,LPCTSTRlpCurrentDirectory,LPSTARTUPINFOlpStartupInfo,LPPROCESS_INFORMATIONlpProcessInformation);CreateProcess的应用逻辑—黑社会逻辑Main.exe:主控程序,黑社会BossA.exe:专门处理任务A的程序,黑社会小弟B.exe:专门处理任务A的程序,黑社会小弟intmain(){…….//遇到两个需要并行执行的任务:任务A和任务BCreateProcess(“A.exe”,…);//叫个小弟来处理任务ACreateProcess(“B.exe”,…);//叫个小弟来处理任务B….//自己继续享受生活}exec函数•exec函数用于创建一个新的进程,新进程以另一个可执行程序为执行脚本。•exec创建的新进程“占用了”原进程的绝大部分资源,进程地址空间中装入了新的可执行程序。exec执行成功之后,原进程就“消失了”。•#includeunistd.h•intexecl(constchar*path,constchar*arg,...)•参数path:可执行文件的路径和名字构成的字符串•arg:新程序的命令行参数1•execl是一个不定参数函数,还可以传入多个命令行参数,最后一个参数必须是NULL。•返回值:-1表示出错exec函数的例子1#includeunistd.hintmain(intargc,char*argv[]){if(execl(/bin/echo,echo,executedbyexecl,NULL)0)perror(Erronexecl);}exec函数的例子2如果还想保留父进程怎么办??#includeunistd.hintmain(intargc,char*argv[]){if(fork()==0){if(execl(/bin/echo,echo,executedbyexecl,NULL)0)perror(Erronexecl);}//父进程做其他事情return0;}exec函数族exec函数族使用区别•exec函数族使用区别–查找方式•表中的前四个函数的查找方式都是完整的文件目录路径,而最后两个函数(以p结尾的函数)可以只给出文件名,系统就会自动从环境变量“$PATH”所指出的路径中进行查找。–参数传递方式•两种方式:逐个列举、将所有参数整体构造指针数组传递•以函数名的第五位字母来区分的,字母为“l”(list)的表示逐个列举的方式,其语法为char*arg;字母为“v”(vertor)的表示将所有参数整体构造指针数组传递,其语法为*constargv[]–环境变量•exec函数族可以默认系统的环境变量,也可以传入指定的环境变量。这里,以“e”(Enviromen)结尾的两个函数execle、execve就可以在envp[]中指定当

1 / 51
下载文档,编辑使用

©2015-2020 m.111doc.com 三一刀客.

备案号:赣ICP备18015867号-1 客服联系 QQ:2149211541

×
保存成功