




已阅读5页,还剩131页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Linux环境高级编程,1,第四讲进程,2,进程,进程环境(第七章)进程控制(第八章)进程关系(第九章),3,进程,进程环境(第七章)进程控制(第八章)进程关系(第九章),4,进程环境,main函数和命令行参数进程的启动和终止环境表和环境变量存储空间布局存储器分配setjmp和longjmp函数,5,进程环境,main函数和命令行参数进程的启动和终止环境表和环境变量存储空间布局存储器分配setjmp和longjmp函数,6,main函数和命令行参数,通常,C程序总是从main函数开始执行main函数原型intmain(intargc,char*argv);参数argc:命令行参数的个数argv:指向命令行参数的各个指针所构成的数组命令行$./testHelloWorld,程序中怎么样获得命令行参数,7,main函数和命令行参数,参数agrv:,argv1,argv0,argv2,.,argvargc-1,argv,8,main函数和命令行参数,程序演示(4.1),9,进程环境,main函数和命令行参数进程的启动和终止环境表和环境变量存储空间布局存储器分配setjmp和longjmp函数,10,进程的终止,8种方式使进程终止正常终止从main返回调用exit调用_exit或_Exit最后一个线程从其启动例程返回最后一个线程调用pthread_exit异常终止,11,进程的终止,异常终止调用abort接到一个信号并终止最后一个线程对取消请求做出响应有关信号、线程的终止方式,后面讨论或者自学,12,进程终止,三个终止函数:exit、_Exit、_exit函数原型:voidexit(intstatus);void_Exit(intstatus);void_exit(intstatus);exit函数执行一个标准I/O库的清理关闭操作(为所有打开流调用fclose函数)后,进入内核_Exit、_exit函数立即进入内核,13,进程终止(4.2),exit等函数的参数status:进程的终止状态程序演示查看进程终止状态echo$?,14,atexit函数,当进程终止时,程序可能需要进行一些自身的清理工作,如资源释放等等atexit函数提供了进行这样工作的机会它允许用户注册若干终止处理函数,当进程终止时,这些终止处理函数将会被自动调用,15,atexit函数,用于注册用户提供的终止处理函数函数原型intatexit(void(*func)(void);参数func:函数指针,返回值为void,无参返回值成功返回0,出错返回非0值,16,atexit函数,程序演示(4.3)注意:先注册的函数,后被运行。调用_exit函数并不会触发终止处理函数,17,进程的启动和终止,Kernel,exitfunc.,用户函数,main函数,C启动例程,终止处理函数,终止处理函数,标准I/O清理函数,_exit,exit不返回,exec,call,call,return,call,return,call,return,Userprocess,_exit,_exit,exit不返回,exit不返回,call,返回,返回,18,进程环境,main函数和命令行参数进程的启动和终止环境表和环境变量存储空间布局存储器分配setjmp和longjmp函数,19,环境表和环境变量,每个进程都会接收到一张环境表通过environ找到环境表externchar*environ;环境字符串:name=value,20,环境表和环境变量,访问环境变量的方法直接使用environ使用getenv和putenv等函数getenv函数用于获取环境变量值函数原型char*getenv(constchar*name);返回与name关联的value的指针,若未找到则返回NULL返回的指针是指向新分配的内存,还是环境表中存在的值?(程序4.4),21,设置环境变量,三种方法:putenvsetenvunsetenvputenv函数将形式为name=value的字符串,放入环境表中;若name已经存在,则先删除其原来的定义。函数原型:intputenv(char*str);,22,设置环境变量,setenv函数原型:intsetenv(constchar*name,constchar*value,intrewrite);setenv将环境变量name的值设置为value。若name已经存在rewrite!=0,则删除其原先的定义rewrite=0,则不删除其原先的定义,23,设置环境变量,unsetenv函数用于删除某个环境变量函数原型intunsetenv(constchar*name);删除name的定义疑问?前两个设置环境变量的函数,都给出了自己的缓冲区存放环境变量。在环境表中是否直接使用这些缓冲区,还是环境表自己分配了缓冲区?(程序4.5),24,进程环境,main函数和命令行参数进程的启动和终止环境表和环境变量存储空间布局存储器分配setjmp和longjmp函数,25,C程序存储空间布局,命令行参数和环境变量,栈堆,未初始化的数据,初始化的数据,正文,Highaddress,Lowaddress,26,C程序存储空间布局,命令行参数和环境变量,栈堆,未初始化的数据,初始化的数据,正文,Highaddress,Lowaddress,CPU执行的机器指令部分,正文段通常是共享、只读的,27,C程序存储空间布局,命令行参数和环境变量,栈堆,未初始化的数据,初始化的数据,正文,Highaddress,Lowaddress,包含了程序中需明确赋初值的变量,如全局变量intmaxcount=99;,28,C程序存储空间布局,命令行参数和环境变量,栈堆,未初始化的数据,初始化的数据,正文,Highaddress,Lowaddress,程序执行之前,将此段中的数据初始化为0,如:longsum1000;,29,C程序存储空间布局,命令行参数和环境变量,栈堆,未初始化的数据,初始化的数据,正文,Highaddress,Lowaddress,用于动态分配内存,30,C程序存储空间布局,命令行参数和环境变量,栈堆,未初始化的数据,初始化的数据,正文,Highaddress,Lowaddress,主要用于支撑函数调用存放参数、局部变量等,31,32,Windows95进程地址空间,33,Windows2000进程地址空间,34,Linux进程地址空间,35,Linux进程地址空间,逻辑地址、线性地址、物理地址?查看进程的地址空间(4.11)$cat/proc/进程ID/maps/proc目录中的文件并不是真正的磁盘文件,而是由内核虚拟出来的文件系统,当前系统中运行的每个进程在/proc下都有一个子目录,目录名就是进程的id,查看目录下的文件可以得到该进程的相关信息。,进程环境,main函数和命令行参数进程的启动和终止环境表和环境变量存储空间布局存储器分配setjmp和longjmp函数,36,内存分配,三个用于内存分配的函数malloc:分配指定字节数的存储区,此存储区中的初始值不确定calloc:为指定数量指定长度的对象分配存储空间,该空间中的每一位都初始化为0realloc:更改(增加或者减少)以前分配区的长度C+中使用new,37,内存分配,函数原型void*malloc(size_tsize);void*calloc(size_tnobj,size_tsize);void*realloc(void*ptr,size_tnewsize);注意:三个函数返回的指针一定是适当对齐的什么是对齐?例如:在一个特定的系统上,如果最严格的对齐要求是,double必须在8的倍数地址单元处开始,那么这三个函数返回的指针部分都应这样对齐,38,内存释放,free函数用于释放已分配的内存,即将内存归还给堆函数原型voidfree(void*ptr);分配了内存,但是没有释放,是内存泄露吗?,39,进程环境,main函数和命令行参数进程的启动和终止环境表和环境变量存储空间布局存储器分配setjmp和longjmp函数,40,setjmp和longjmp函数,voidg()voidf()g();voidmainf();,首先查看一个例子在左侧的代码中,main函数调用了f函数,f函数中又调用了g函数假设当g函数内部处理出错时,希望main函数能够感知到这一出错情况如何实现?,41,setjmp和longjmp函数,voidg()voidf()g();voidmainf();,g函数内部处理出错,main函数能被通知到,可能的方法:使用goto语句?g函数通过返回值通知f函数,f函数再通过返回值通知main函数?(考虑函数调用深度)使用setjmp和longjmp使用C+异常处理,42,setjmp和longjmp函数,setjmp和longjmp函数实现函数之间的跳转函数原型intsetjmp(jmp_bufenv);voidlongjmp(jmp_bufenv,intval);setjmp函数用于设置跳转的目的位置longjmp函数进行跳转,43,setjmp和longjmp函数,参数与返回值:env:保留了需要返回的位置的堆栈情况setjmp的返回值:直接调用该函数,则返回0;若由longjmp的调用,导致setjmp被调用,则返回val(longjmp的第二个参数)根据演示程序,说明两个函数(程序演示4.6),44,各类变量的情况,当调用longjmp函数后,在main中的各类变量的值是否改变回原来的值呢?程序演示(4.7)g+-otesttest.cppg+-O-otesttest.cpp全局变量、静态变量、易失变量不受优化的影响在非优化的版本,所有变量都存储在内存中在优化的版本,自动变量和寄存器变量存储在寄存器中,45,46,变量回滚,typedefstructunsignedj_sp;/堆栈指针寄存器unsignedj_ss;/堆栈段unsignedj_flag;/标志寄存器unsignedj_cs;/代码段unsignedj_ip;/指令指针寄存器unsignedj_bp;/基址指针unsignedj_di;/目的指针unsignedj_es;/附加段unsignedj_si;/源变址unsignedj_ds;/数据段jmp_buf;,47,变量回滚问题,保证局部变量在longjmp过程中一直保存它的值的方法:把它声明为volatile变量。(适合那些在setjmp执行和longjmp返回之间会改变的变量)存放在内存中的变量,将具有调用longjmp时的值,而在CPU和浮点寄存器中的变量则恢复为调用setjmp函数时的值优化编译时,register和auto变量都存放在寄存器中,而volatile变量仍存放在内存,48,变量回滚问题,volatile变量:一般在多线程中使用的比较多例如有一个intx,有两个线程都要对其读写有些编译器或CPU会将x保存在寄存器中,读的时候直接读取寄存器中的内容,而不是真实的x在内存中的内容线程1,对x进行加1操作,此时内存中x的值为2线程2想读x,结果从寄存器中读出1给变量加上volatile,指示程序每次读写变量都必须从内存中读取,不要进行缓存(寄存器),自动变量的潜在问题,#include#defineDATAFILEdatafileFILE*open_data(void)FILE*fp;chardatabufBUFSIZ;/*setvbufmakesthisthestdiobuffer*/if(fp=fopen(DATAFILE,r)=NULL)return(NULL);if(setvbuf(fp,databuf,BUFSIZ,_IOLBF)!=0)return(NULL);return(fp);/*error*/,问题?,49,自动变量的潜在问题,问题:open_data函数返回后,它在栈上所使用的空间将由下一个被调用函数所占用但是标准I/O库仍使用位于栈上的databuf缓冲区存在冲突和混乱解决办法:使用全局存储空间使用静态存储空间从堆中分配,50,setjmp和longjmp函数,voidg()voidf()g();voidmainf();,g函数内部处理出错,main函数能被通知到,可能的方法:使用goto语句?g函数通过返回值通知f函数,f函数再通过返回值通知main函数?(考虑函数调用深度)使用setjmp和longjmp使用C+异常处理(4.12),51,Resourcelimits,Everyprocesshasasetofresourcelimits,someofwhichcanbequireandchangedbyfollowingfunctions.#include#includeintgetrlimit(intresource,structrlimit*rlptr);intsetrlimit(intresource,conststructrlimit*rlptr);structrlimitrlim_trlim_cur;/*softlimit:currentlimit*/rlim_trlim_max;/*hardlimit:maximumvalueforrlim_cur*/,52,Resourcelimits(Cont.),resourcemustbeoneof:RLIMIT_CPU.CPUtimelimitinseconds.Whentheprocessreachesthesoftlimit,itissentaSIGXCPUsignal.RLIMIT_DATA.Themaximumsizeoftheprocessdatasegment(initializeddata,uninitializeddata,andheap).RLIMIT_FSIZE.Themaximumsizeoffilesthattheprocessmaycreate.AttemptstoextendafilebeyondthislimitresultindeliveryofaSIGXFSZsignal.RLIMIT_LOCKS.Alimitonthecombinednumberofflock()locksandfcntl()leasesthatthisprocessmayestablish(Linux2.4andlater).,53,Resourcelimits(Cont.),RLIMIT_MEMLOCK.ThemaximumnumberofbytesofvirtualmemorythatmaybelockedintoRAMusingmlock()andmlockall().RLIMIT_NOFILE.Specifiesavalueonegreaterthanthemaximumfiledescriptornumberthatcanbeopenedbythisprocess.RLIMIT_NPROC.ThemaximumnumberofprocessesthatcanbecreatedfortherealuserIDofthecallingprocess.RLIMIT_STACK.Themaximumsizeoftheprocessstack,inbytes.Uponreachingthislimit,aSIGSEGVsignalisgenerated.Etc.,54,Resourcelimitation,Threerulesgovernthechangingoftheresourcelimits:Asoftlimitcanbechangedbyanyprocesstoavaluelessthanorequaltoitshardlimit.Anyprocesscanloweritshardlimittoavaluegreaterthanorequaltoitssoftlimits.Onlysuperuserprocesscanraiseahardlimit.,55,Getrlimit.c,Linux,Solaris,56,进程环境,main函数和命令行参数进程的启动和终止环境表和环境变量存储空间布局存储器分配setjmp和longjmp函数,57,进程,进程环境(第七章)进程控制(第八章)进程关系(第九章),58,进程控制,进程标识符fork等函数exit函数wait等函数exec等函数更改用户ID和组IDsystem函数进程会计用户标识和进程时间,59,进程标识符,每个进程都有一个非负整型表示的唯一进程ID进程ID总是唯一的当进程终止后,其ID值可以重用在unix中ID为0的进程:调度进程,称为swapperID为1的进程:init进程,自举过程结束时由内核调用ID为2的进程:页守护进程,负责支持虚拟存储系统的分页操作,60,进程标识符,获取进程常见标识符调用进程的进程ID:pid_tgetpid();调用进程的父进程ID:pid_tgetppid();调用进程的实际用户ID:uid_tgetuid();调用进程的有效用户ID:uid_tgeteuid();调用进程的实际组ID:gid_tgetgid();调用进程的有效组ID:gid_tgetegid();查看进程情况(4.8)$ps-ef|less,61,进程控制,进程标识符fork等函数exit函数wait等函数exec等函数更改用户ID和组IDsystem函数进程会计用户标识和进程时间,62,fork函数,一个进程可以调用fork函数创建一个新进程新进程被称为子进程函数原型pid_tfork(void);返回值fork函数调用一次,但是返回两次在子进程中返回0,在父进程中返回子进程ID,出错返回-1通过返回值,可以确定是在父进程还是子进程中,63,fork函数,子进程和父进程继续执行fork调用之后的指令子进程是父进程的副本子进程获得父进程数据空间、堆和栈的副本父子进程并不共享这些存储空间父子进程共享正文段(只读的)为了提高效率,fork后不并立即复制父进程空间,采用了COW(Copy-On-Write)当父子进程任意之一,要修改数据段、堆、栈时,进行复制操作,但仅复制修改区域,64,fork函数,程序演示(4.9)为什么write调用的输出只有一次,而printf调用的输出出现了两次?子进程中,变量的值改变了;而父进程中,变量的值没有改变。原因?,65,fork函数,为什么write调用的输出只有一次,而printf调用的输出出现了两次?write调用是不带用户空间缓冲的。在fork之前调用write,其数据直接写到了标准输出上标准I/O库是带缓冲的,当标准输出连接到终端设备时,它是行缓冲,否则为全缓冲。当printf输出到终端设备时,由于遇到换行符,因此缓冲被刷。子进程的数据空间中无缓冲内容当重定向到文件时,变为全缓冲。fork后,子进程的数据空间中也有内容。所以输出两次,66,文件共享,在上例中:在重定向父进程的标准输出时,子进程的标准输出也被重定向了fork的一个特性:父进程的所有打开文件描述符,都被复制到子进程中。,67,父子进程共享文件对象,task_struct,.,files,.,.,files_struct,fd0,fd1,fd2,.,files_struct,file,f_pos,f_dentry,文件标志,索引节点号,文件各信息,inode,task_struct,.,files,.,.,files_struct,fd0,fd1,fd2,files_struct,父进程,子进程,.,file,f_pos,f_dentry,文件标志,.,f_pos,f_dentry,文件标志,.,f_pos,f_dentry,文件标志,索引节点号,文件各信息,inode,索引节点号,文件各信息,inode,68,父子进程文件共享,父子进程对同一文件使用了一个文件偏移量上例中,父进程等待了子进程两秒钟,所以他们的输出才没有混乱;否则有可能出现乱序文件描述符的常见处理方式父进程等待子进程完成。父进程无需对描述符做任何处理,当子进程终止后,文件偏移量已经得到了相应的更新父子进程各自执行不同的程序段,各自关闭文件描述符,69,Differencebetweenparentandchildafterfork,Propertiesinheritedfromparent:Realuser/groupID,effectiveuser/groupIDSupplementarygroupIDProcessgroupIDSessionID;Controlterminal.Set-user/group-IDcurrentworkdirectoryFilemodemaskSignalmask;environment;Resourcelimits,Differencebetweenparentandchild:returnvaluefromforkProcessIDParentprocessID;Thechildsvaluefortms_utime,tms_stime,tms_cutime,tms_ustimearesetto0;FilelocksdonotbeinheritedbychildPendingalarmareclearedforchild,70,fork函数常见用法,一个父进程希望复制自己,使父子进程同时执行不同的代码段网络服务程序中,父进程等待客户端的服务请求,当请求达到时,父进程调用fork,使子进程处理该次请求,而父进程继续等待下一个服务请求到达一个进程要执行一个不同的程序子进程从fork返回后,立即调用exec执行另外一个程序,71,72,fork,程序演示(4.10),vfork函数,vfork与fork的函数原型相同,但两者的语义不同vfork用于创建新进程,而该新进程的目的是exec一个新程序(执行一个可执行的文件)由于新程序将有自己的地址空间,因此vfork函数并不将父进程的地址空间完全复制到子进程中。子进程在调用exec或exit之前,在父进程的地址空间中运行,73,vfork函数,vfork函数保证子进程先执行,在它调用exec或者exit之后,父进程才可能被调度执行程序演示(4.13)子进程中对glob、var加1操作,结果改变了父进程中的变量值。原因?,74,vfork函数,调用_exit,还是exit?exit被调用时,将冲刷所有的标准I/O流。在传统实现中,同时也将关闭标准I/O流。即表示标准输出FILE对象的相关存储区将被清0由于父子进程共享同一地址空间,当父进程恢复运行并调用printf时,不会产生任何输出,它返回-1实际上,大多数exit的现代实现不再关闭流。因为进程即将终止,内核将关闭所有已打开的文件描述符,75,进程控制,进程标识符fork等函数exit函数wait等函数exec等函数更改用户ID和组IDsystem函数进程会计用户标识和进程时间,76,exit函数,正常终止从main返回调用exit:ISOC定义调用_exit或_Exit:前者由ISOC定义,后者由POSIX.1定义最后一个线程从其启动例程返回最后一个线程调用pthread_exit异常终止调用abort:产生SIGABRT信号接到某些信号最后一个线程对取消请求做出响应,77,exit函数,不管进程如何终止,最后都会执行内核中的同一段代码:为相应进程关闭所有打开描述符,释放内存等等若父进程在子进程之前终止了,则子进程的父进程将变为init进程,其PID为1;保证每个进程都有父进程当子进程先终止,父进程如何知道子进程的终止状态(exit(5))内核为每个终止子进程保存了终止状态等信息父进程调用wait等函数,可获取该信息,78,exit函数,当父进程调用wait等函数后,内核将释放终止进程所使用的所有内存,关闭其打开的所有文件对于已经终止、但是其父进程尚未对其调用wait等函数的进程,被称为僵尸进程程序演示(4.14后台启动)psDefunct:死了的对于父进程先终止,而被init领养的进程会是僵尸进程吗?init对每个终止的子进程,都会调用wait函数,获取其终止状态,79,进程控制,进程标识符fork等函数exit函数wait等函数exec等函数更改用户ID和组IDsystem函数进程会计用户标识和进程时间,80,wait等函数,当一个进程正常获知异常终止时,内核就向其父进程发送SIGCHLD信号父进程可以选择忽略该信号,也可以提供信号处理函数系统的默认处理方式:忽略该信号,81,wait函数,wait函数可用于获取子进程的终止状态函数原型pid_twait(int*statloc);参数与返回值statloc:可用于存放子进程的终止状态返回值:若成功返回终止进程ID,出错返回-1,82,wait函数,调用wait函数之后,进程可能出现的情况如果所有子进程都还在运行,则阻塞等待,直到有一个子进程终止,wait函数才返回如果一个子进程已经终止,正等待父进程获取其终止状态,则wait函数会立即返回若进程没有任何子进程,则立即出错返回注意:若接收到信号SIGCHLD后,调用wait,通常wait会立即返回,83,wait函数,参数statlocstatloc可以为NULL,表明父进程不需要子进程的终止状态。为了防止子进程成为僵尸或者需等待子进程结束若statloc不是空指针,则进程终止状态就存放在它指向的存储单元中statloc指向的存储单元,存放了诸多信息,可以通过系统提供的宏获取,84,获取终止状态的宏,85,wait函数,程序演示,说明如何获取exit状态(4.15),86,waitpid函数,如果一个进程有几个子进程,那么只要有一个子进程终止,wait就返回如何才能等待一个指定的进程终止?调用wait,然后将其返回的进程ID和所期望的进程ID进行比较如果ID不一致,则保存该ID,并循环调用wait函数,直到等到所期望的进程ID为止下一次又想等待某一特定进程时,先查看已终止的进程列表,若其中已有要等待的进程,则无需再调用wait函数,87,waitpid函数,waitpid函数可用于等待某个特定的进程函数原型pid_twaitpid(pid_tpid,int*statloc,intoptions);参数和返回值成功返回进程ID,失败返回-1statloc:存放子进程终止状态,88,waitpid函数,参数pidpid=-1:等待任一子进程,同waitpid0:等待进程ID为pid的子进程pid=0:等待其组ID等于调用进程组ID的任一子进程pid-1:等待其组ID等于pid绝对值的任一子进程,89,waitpid函数,参数options:可以为0,也可以是以下常量或运算的结果WCONTINUEDWUNTRACEDWNOHANG:若pid指定的子进程并不是立即可用的,则waitpid不阻塞,此时其返回0程序演示waitpid的非阻塞版本(4.16),90,waitpid函数,waitpid函数提供了wait函数没有的三个功能:waitpid可等待一个特定的进程,而wait则返回任一终止子进程的状态waitpid提供了一个wait的非阻塞版本。有时用户希望取得一个子进程的状态,但不想阻塞waitpid支持作业控制,91,waitpid函数,程序演示(4.17)需求:如果一个进程fork了一个子进程,但不要它等待子进程终止,也不希望子进程处于僵死状态直到父进程终止技巧:调用fork进程两次,92,wait3andwait4Functions,#includepid_twait3(int*status,intoptions,structrusage*rusage)pid_twait4(pid_tpid,int*status,intoptions,structrusage*rusage)Bothreturn:processIDifOK,0,or-1onerror.Thesetwofunctionsallowsthekerneltoreturnasummaryofresourceusedbytheterminatedprocessandallitschildprocesses.TheresourceinfoincludessuchastheamountofuserCPUtime,theamountofsystemCPUtime,andthelike.,structtimevalru_utime;/*usertimeused*/structtimevalru_stime;/*systemtimeused*/longru_msgsnd;/*messagessent*/longru_msgrcv;/*messagesreceived*/longru_nsignals;/*signalsreceived*/,93,进程控制,进程标识符fork等函数exit函数wait等函数exec等函数更改用户ID和组IDsystem函数进程会计用户标识和进程时间,94,exec等函数,进程调用exec等函数用于执行另一个可执行文件当进程调用一种exec函数时,该进程执行的程序完全替换为新程序而新程序则从其main函数开始执行exec并不创建新进程,所以前后的进程ID并未改变,exec只是用一个全新的程序替换了当前进程的正文、数据、堆和栈段,95,execl函数,函数原型intexecl(constchar*pathname,constchar*arg0,./*(char*)0*/);返回值与参数出错返回-1,成功不返回值pathname:要执行程序的路径名可变参数:要执行程序的命令行参数,以“(char*)0”结束,96,execl函数,调用方法:execl(“./test”,“./test”,“Hello”,“World”,(char*)0);程序演示(4.18)进程ID没有改变execl调用成功,且新程序执行完毕,execl没有返回到下一行代码执行。为什么?,97,其他类exec函数,execv函数intexecv(constchar*pathname,char*constargv);execle函数intexecle(constchar*pathname,constchar*arg0,./*(char*)0,char*constenvp*/);最后一项是一个指向环境字符串指针数组的指针,98,其他类exec函数,execve函数intexecve(constchar*pathname,char*constargv,char*constenvp);execlp函数intexeclp(constchar*filename,constchar*arg0,./*(char*)0*/);指定了要执行的文件名。路径信息:从环境变量PATH中获取PATH=/bin:/usr/bin:/usr/local/bin/:.,99,其他类exec函数,execvp函数intexecvp(constchar*filename,char*constargv);,100,exec类函数,execlexecvexecleexecveexeclpexecvp六个函数开头均为exec,所以称为exec类函数l:表示list,即每个命令行参数都说明为一个单独的参数v:表示vector,命令行参数放在数组中e:调用者提供环境表p:表示通过环境变量PATH,查找执行文件,101,102,execFunctions(Cont.),PcessIDandparentprocessIDrealuserIDandrealgroupIDsupplementarygroupIDsprocessgroupIDsessionIDcontrollingterminaltimeleftuntilalarmclockcurrentworkdirectoryrootdirectoryfilemodecreatemaskfilelocksprocesssignalmaskpendingsignalsresourcelimitstms_utime,tms_stime,tms_cutime,tms_cstime,exec类函数,通常,只有execve是内核的系统调用,其他5个都是库函数,execvp,execlp,execl,execle,execv,execve(系统调用),buildargv,buildargv,TryeachPATHprefix,useenviron,buildargv,103,进程控制,进程标识符fork等函数exit函数wait等函数exec等函数更改用户ID和组IDsystem函数进程会计用户标识和进程时间,104,用户ID和组ID,第一种ID:Linux是一个多用户的操作系统。每个用户都有一个ID,用以唯一标识该用户。这个ID,被称为UID。每个用户都属于某一个组,组也有一个ID。这个ID,被称为组ID,GID。第二种ID:文件所有者相关文件所有者ID:拥有某文件的用户的ID文件所有者组ID:拥有某文件的用户所属组的ID,105,用户ID和组ID,第三种ID:实际用户ID和实际组ID进程的实际用户ID:运行该进程的用户的ID进程的实际组ID:运行该进程的用户所属的组ID第四种ID:有效用户ID和有效组ID进程的有效用户ID:用于文件访问权限的检查进程的有效组ID:,大多数情况下有效用户/组ID实际用户/组ID,106,用户ID和组ID,设置用户ID位和设置组ID位在可执行文件的权限标记中,有一个“设置用户ID位”若该位被设置,表示:执行该文件时,进程的有效用户ID变为文件的所有者对于设置组ID位类似第五种ID:保存的设置用户ID保存的设置组ID上述两者在执行一个程序时(exec)包含了有效用户ID和有效组ID的副本,107,更改用户ID和组ID,系统的权限检查是基于用户ID或组ID当程序需要增加特权,或需要访问当前并不允许访问的资源时,需要更换自己的用户ID或组ID可以用setuid设置实际用户ID和有效用户ID;setgid设置实际组ID和有效组ID,108,setuid和setgid函数,intsetuid(uid_tuid);intsetgid(gid_tgid);改变用户/组ID的规则若进程具有超级用户权限,则setuid将实际用户ID、有效用户ID、保存的设置用户ID设置为uid若进程没有超级用户权限,但uid等于实际用户ID或保存的设置用户ID,则setuid只将有效用户ID设置为uid,不改变实际用户ID和保存的设置用户ID若以上条件不满足,返回-1,errno设为EPERM,109,用户ID和组ID,只有超级用户进程可以更改实际用户ID实际用户ID是在用户登录时,由login程序设置的login是一个超级用户进程,当它调用setuid时,会设置所有三个用户ID仅当对程序文件设置了设置用户ID位时,exec才会设置有效用户ID。任何时候都可以调用setuid,将有效用户ID设置为实际用户ID或保存的设置用户ID保存的设置用户ID是由exec复制有效用户ID而得来的,110,用户ID和组ID,例子:man联机手册man程序文件是由名为man的用户拥有的,且设置用户ID位已设置。当执行exec此程序时,用户ID:实际用户ID我们的用户ID有效用户IDman保存的设置用户IDmanman程序访问要手册页,而手册页文件是由名为man的用户所拥有的。有效用户ID是man,所以可以访问这些文件,111,用户ID和组ID,在man代表我们运行任一命令之前(使有效用户ID等于我们的用户ID),它调用setuid(getuid()。(不是超级用户进程)getuid返回实际用户ID,即我们的用户ID实际用户ID我们的用户ID有效用户ID我们的用户ID保存的设置用户IDman这样,以我们的用户ID作为其有效用户ID而运行。这就意味着能访问的只有我们通常可以访问的,而没有任何额外的权限,112,用户ID和组ID,当man需要对其手册页进行访问时,又需要将其有效用户ID改为manman调用setuid(man)实际用户ID我们的用户ID有效用户IDman保存的设置用户IDman由于setuid的参数等于保存的设置用户ID,所以setuid可以成功修改有效用户ID这就是保存的设置用户ID的作用,113,用户ID和组ID,114,进程控制,进程标识符fork等函数exit函数wait等函数exec等函数更改用户ID和组IDsystem函数进程会计用户标识和进程时间,115,system函数,用于执行一个shell命令函数原型intsystem(constchar*cmdstring);cmdstring:shell命令程序演示(4.19),116,system函数,system是通过fork、exec、waitpid等实现的,因此有三种返回值即fork失败,exec失败,waitpid失败,117,进程会计,进程会计记录包含命令名,CPU时间总量,用户ID和组ID,启动时间等等,118,进程控制,进程标识符fork等函数exit函数wait等函数exec等函数更改用户ID和组IDsystem函数进程会计用户标识和进程时间,119,用户标识,getlogin函数可以获取当前用户的登录名函数原型char*getlogin();返回值调用此函数的进程没有连接到用户登录时所用的终端,则本函数会失败,返回NULL这种进程通常称为守护进程成功返回登录名程序演示(4.20),120,进程时间,times函数用于获取墙上时钟时间、用户CPU时间、系统CPU时间函数原型clock_ttimes(structtms*buf);times填写buf指向的tms结构structtmsclock_ttms_utime;/用户CPU时间clock_ttms_stime;/系统CPU时间.;,121,进程时间,返回值返回墙上时钟时间该值相对于过去某个时刻测量的,不能使用其绝对值。只能用相对值,122,进程控制,进程标识符fork等函数exit函数wait等函数exec等函数更改用户ID和组IDsystem函数进程会计用户标识和进程时间,123,进程,进程环境(第七章)进程控制(第八章)进程关系(第九章),124,进程关系,进程组会话控制终端,125,进程组,每个进程除了有一个进程ID外,还属于一个进程组进程组是一个或多个进程的集合。通常,它们与同一作业关联,可以接收来自同一终端的各种信号。每个进程组有一个唯一的进程组ID每个进程组都可以有一个组长进程;组长进程的标识是:其进程组ID等于组长进程ID,126,进程组,只要进程组中还有一个进程存在,则进程组就存在,与
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 南京市租赁合同样本(含装修变更权约定)
- 休闲农业租赁合同附加乡村旅游服务协议
- 线路板智能工厂建设项目建筑工程方案
- 含氟高端精细化学品生产线项目技术方案
- 公路工程物资采购与管理模式优化研究
- 复合地基考试试题及答案
- 文化创意产业园区品牌影响力提升与2025年产业集聚的生态构建报告
- 昆明律师咨询方案
- 海北法律咨询方案
- 2025年风电项目噪声环境影响后评价与治理措施报告
- 中石化内部控制培训课件
- 2025年青少年法律知识竞赛试题库(试题及答案)
- 收单商户管理办法
- DB42∕T 2130-2023 《林业生态产品清单》
- 分类管理理念下国有企业股权投资后评价体系的构建与实践
- 2025年合规专业面试题及答案
- 西畴殡葬管理办法
- 新生儿支气管肺炎护理查房
- 小学生意外伤害课件
- 银行外包人员管理办法
- 外贸订单发货管理办法
评论
0/150
提交评论