17-Linux+C视频课程之进程篇_第1页
17-Linux+C视频课程之进程篇_第2页
17-Linux+C视频课程之进程篇_第3页
17-Linux+C视频课程之进程篇_第4页
17-Linux+C视频课程之进程篇_第5页
已阅读5页,还剩31页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

进程与信号

--进程篇

主讲:刘晓涛1进程结构\类型和时间安排以多种方法启动新进程父进程\子进程\僵进程议程概述Overview进程与信号是Unix/Linux操作环境的基石不管是系统管理员还是程序员都必须掌握它们才能更好的管理与开发3什么是进程?Unix98技术规范把进程定义为:

一个其中运行有一个或多个线程的地址空间和线程要求使用的系统资源.进程是一个运行中的程序(通俗一点)Linux是多用户/多任务系统,同时可运行多个进程进程是由程序代码/数据/变量(占用着系统内存)/打开的文件(文件描述符)和一个环境组成Linux系统会让进程共享代码和系统库,任何时刻内存中只有代码的一份拷贝4进程结构“ps–af”可以看到正在运行的进程每个进程都有一个从2开始的PID,1一般是给init进程保留的(它负责管理其他的进程)进程是不能对用来存放程序代码的内存区域进行写操作的(代码以只读方式加载),正因为如此,两个进程才能安全的共享一份代码进程有自己的堆栈空间,函数的局部变量与控制函数调用与返回的信息保存在堆栈空间中进程有自己的环境空间,其环境变量设置出来的环境是供该进程专用的进程有自己的程序计数器,来记录执行到了什么位置5进程结构/proc下有一些特殊文件,允许在进程运行时透视到进程内部6进程表进程表是一种数据结构,存储当前加载在内存中的所有进程的有关信息(如PID,状态,命令字符串)进程表的长度有限,所以系统能够同时支持的进程个数也是有限的只要划分给进程表使用的内存里还有容纳数据项的地方,就允许继续启动进程系统通过PID对进程进行管理,PID是进程表的一个索引7查看进程ps–af:查看用户进程

a—all用户进程

f—查看进程完整信息ps–ax:查看系统进程

可看到init(进程管理器),它是所有进程的祖先父进程启动子进程状态R:进程处于可运行状态,不一定正在运行8进程调度UNIX系统通过一个进程调度器来决定下一个时间片应该分配个哪一个进程优先级比较高的进程运行的比较频繁,而包括后台任务在内的低优先级进程运行就不那么频繁了进程的优先级基数可以用nice命令设置,用renice命令调整ps–l

可看到:

“STAT”状态栏多了个’N’,表示此进程的优先级基数已经不是原来的默认值了

PPID—父进程的PID在某些情况下,只要还有高优先级进程可以运行,低优先级进程就根本不会运行9启动新进程可以让一个程序在另一个程序的内部运行#include<stdlib.h>intsystem(constchar*string);如果无法启动shell运行命令,返回127,出现不能执行system调用的其他错误是返回-110动手试一试(system)#include<stdlib.h>#include<stdio.h>

intmain(){printf("Running

pswithsystem\n");system("ps−ax");printf("Done.\n");exit(0);}11因为system函数要使用一个shell来启动程序,所以我们可以把它放到后台去运行,把函数改为:

system("ps−ax&");System函数不是启动其他进程的理想手段,因为它必须用一个shell来启动程序,效率低,而且对shell的安装情况和它所处的环境的依赖也很大更好的办法是:低层接口exec12替换一个进程映像一个exec函数可以把当前进程替换为一个新进程,新进程有path或file参数指定#include<unistd.h>char**environ;int

execl(constchar*path,constchar*arg0,...,(char*)0);int

execlp(constchar*file,constchar*arg0,...,(char*)0);int

execle(constchar*path,constchar*arg0,...,(char*)0,constchar*envp[]);int

execv(constchar*path,constchar*argv[]);int

execvp(constchar*file,constchar*argv[]);int

execve(constchar*path,constchar*argv[],constchar*envp[]);13#include<unistd.h>constchar*ps_argv[]={"ps","−ax",0};constchar*ps_envp[]={"PATH=/bin:/usr/bin","TERM=console",0};execl("/bin/ps","ps","−ax",0);/*assumespsisin/bin*/execlp("ps","ps","−ax",0);/*assumes/binisinPATH*/execle("/bin/ps","ps","−ax",0,ps_envp);/*passesownenvironment*/execv("/bin/ps",ps_argv);execvp("ps",ps_argv);execve("/bin/ps",ps_argv,ps_envp);14动手试一试(execlp)#include<unistd.h>#include<stdio.h>intmain(){printf("Running

pswithexeclp\n");execlp("ps","ps","−ax",0);printf("Done.\n");exit(0);}Whenwerunthisprogram,pexec.c,wegettheusualpsoutput,butnoDone.messageatall.Ps输出中也没有pexec的进程信息(被替换掉了)15程序说明execlp会在PATH环境变量给出的子目录中搜索名为ps的程序,然后执行它,并用它替换掉我们的pexec程序

对一个由exec函数启动的进程来说,它的参数表和环境加在一起的总长度由ARG_MAX限制,Linux上是128k字节

如果没出现错误,exec函数不返回的,出现错误是返回-1,并且会设置错误变量errno

由exec启动的新进程继承了pid等许多东西,已经打开的文件描述符在新进程中还是打开的16复制一个进程映像如果想用进程同时执行多个函数有二种方法:

a.使用线程

b.从原程序里创建新进程(如init)

不能像exec调用一样用新进程替换正在执行的进程调用fork可以创建一个全新的进程,该系统调用对当前进程进行复制,新进程与原进程执行的是相同的代码,但新进程有自己的数据空间/环境/文件描述符17fork函数#include<sys/types.h>#include<unistd.h>pid_t

fork(void);

在父进程中调用fork返回的是新进程的PID在子进程中调用fork将返回0如果fork失败,将返回-1失败的原因通常是父进程拥有子进程的个数超过CHILD_MAX,此时errno将被设置为EAGAIN如失败原因是进程表没有足够的空间或虚拟内存不足,errno变量将被设置为ENOMEM18fork函数19fork典型用法pid_t

new_pid;new_pid=fork();switch(new_pid){ case−1:/*Error*/ break; case0:/*Wearechild*/ break; default:/*Weareparent*/ break;}20动手试一试(fork.c)#include<sys/types.h>#include<unistd.h>#include<stdio.h>intmain(){pid_tpid;char*message;intn;printf("forkprogramstarting\n");pid=fork();switch(pid){case−1:perror("forkfailed");exit(1);case0:message="Thisisthechild";n=5;break;default:message="Thisistheparent";n=3;break;}for(;n>0;n−−){puts(message);sleep(1);}exit(0);}21Output:$./forkforkprogramstartingThisistheparentThisisthechildThisistheparentThisisthechildThisistheparentThisisthechild$ThisisthechildThisisthechild22程序说明程序在调用fork的时候被分为两个独立的进程.,程序靠fork的非零返回值确定父进程父进程在子进程之前结束了23等待进程可以通过调用wait安排在子进程结束之后再结束父进程

#include<sys/types.h>#include<sys/wait.h>pid_t

wait(int*stat_loc);

wait调用会使父进程暂停执行,直到它的一个子进程结束为止返回值是子进程的PIDstat_loc存储状态信息,状态信息允许父进程判定子进程的退出状态24sys/wait.h中的宏解读状态信息25动手试一试(wait.c)#include<sys/types.h>#include<sys/wait.h>#include<unistd.h>#include<stdio.h>intmain(){pid_tpid;

char*message;

intn;int

exit_code;printf("forkprogramstarting\n");pid=fork();switch(pid){case−1:

perror(“forkfailed”);

exit(1);case0:

message=“Thisisthechild”;

n=5;

exit_code=37;

break;default:

message=“Thisistheparent”;

n=3;exit_code=0;break;}26动手试一试(wait)续for(;n>0;n−−){

puts(message); sleep(1);}if(pid!=0){

int

stat_val;

pid_t

child_pid;

child_pid=wait(&stat_val);

printf("Childhasfinished:PID=%d\n",child_pid);

if(WIFEXITED(stat_val))

printf("Childexitedwithcode%d\n",WEXITSTATUS(stat_val));else

printf("Childterminatedabnormally\n");}exit(exit_code);}27Output$./waitforkprogramstartingThisistheparentThisisthechildThisistheparentThisisthechildThisistheparentThisisthechildThisisthechildThisisthechildChildhasfinished:PID=410Childexitedwithcode37$28僵进程当子进程结束了,而父进程还没有结束,这时候进程表中代表子进程的数据项是不会立即释放的,虽然不再活跃了,可子进程还停留在系统中,因为它的退出码还需要保存起来以备父进程使用(如wait调用)该子进程就是“僵进程”29动手试一试(Zombies)上一个例子修改一下,把输出次数对调一下:fork2.cswitch(pid){case−1:perror("forkfailed");exit(1);case0:message="Thisisthechild";n=3;break;default:message="Thisistheparent";n=5;break;}30程序说明运行:fork2&在子进程结束之后父进程结束之前执行ps程序,就会看到僵进程了

如果父进程非正常结束了,子进程就自动会把init作为自己的父进程要尽量避免僵进程的产生,因为在init进行清理之前,它们一直消耗系统资源31waitpid#include<sys/types.h>#include<sys/wait.h>pid_t

waitpid(pid_tpid,int*stat_loc,intoptions);

pid:准备等待的子进程的PID,如果是-1,waitpid将返回每一个子进程的信息Options参数允许我们改变waitpid的行为,最有用的选项是WNOHANG,它的作用是防止waitpid把调用者的执行挂起32Waitpid续父进程周期性地检查某个特定的子进程是否已经结束

waitpid(child_pid,(int)*0,WNOHANG);返回0:如果子进程未结束或未被意外终止返回child_pid:如果子进程已经结束返回-1:操作失败时,并设置errno变量没有子进程:errno设置为ECHILD调用被一个信号中断了:errno设置为EINTR选项参数不合法:errno设置为EINVAL33输入输出重定向#include<stdio.h>#include<ctype.h>intmain(){int

ch;while((ch=getchar())!=EOF){putchar(toupper(ch));}exit(0);}$./upperhelloTHEREHELLOTHERE^D$$catfile.txtthisisthefile,file.txt,itisalllowercase.$upper

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论