笔记整理—linux进程部分(3)wait工作原理与exec族函数

        当子进程结束时,系统向其父进程发送SIGCHILD信号,父进程调用wait()后将阻塞的等待SIGCHILD信号。

        父子进程之间是异步的,父子进程之间不能直接通信,所有使用SIGCHILD信号去实现回收子进程的僵尸状态。如果父进程没有子进程,又被调用wait()则会返回err。

pid_t wait(&status);//status返回状态

        父进程通过wait得到status后得到子进程的状态信息。wait返回pid_t返回的是多个子进程其中之一的进程,所以要根据wait返回的pid_t去判断谁被回收了(正常的终止状态为return、exit、_exit。非正常状态为kill、信号等方式实现结束。)使用宏获得子进程的退出方式:WIFEXITED正常终止;WIFSIGNALEN非正常终止 WEXITSTATUS得到正常终止进程的返回值。

        waitpid(),wait函数不能挑选回收的子进程,但waitpid可用指定所等待的pid号进行回收,waitpid支持阻塞和非阻塞两种工作模式。

pid_t waitpid(pid_t pid,int &status,int options);
options=0则表示忽略
WNOHANG:非阻塞

        ret=waitpid(-1,&status,0);-1意为不管子进程的pid,&status为返回状态,0为阻塞态,ret为本次返回的PID。

pid=fork();
ret=waitpid(pid,&status,WNOHANG);

        ret=0,子进程没结束,=-1,pid号错误。

        竞态,就是竞争状态,在多个进程程序中,多个进程同时抢占系统资源,静态对OS是有害的,无法确定父子进程谁先执行,则结果不可知,所以要尽可能的避免竞态,应在合适的地方对可能存在竞态的地方进行消除,如使用sleep()。

        exec族函数,当fork()出来的子进程可以在if()中去进行区别的执行,但是这不太灵活,要把源码贴过来执行,又例如希望执行ls -a但没有源码进行解析,exec族可运行新的可执行程序(编译好的程序可直接调用)。例如,以hello.out为子程序,在主程程序fork子进程用exec加载hello.out同时运行子进程。

        execl和execv。execl族使用当去声明进程的环境变量(extern char **environ)

int execl(const char *path, const char *arg, ...);
int execv(const char *path, char *const argv[]);

        这两个exec都可以用于执行程序,区别在于参数列表的表达方式不同,execl的参数列表以NULL结尾。

int execvp(const char *file, char *const argv[]);
int execlp(const char *file, const char *arg, ...);

        对比上一组函数不难看出,只有在第一个参数上有区别,path必须是全路径,找不到就err,file找到就会与path一样,如果还是找不到就回去PATH环境变量里找,再找不到就err。

int execle(const char *pathname, const char *arg, ...
                       /*, (char *) NULL, char *const envp[] */);
int execvpe(const char *file, char *const argv[],char *const envp[]);

        多出一个envp做形参,envp就是environment环境变量数字,与梦想时可以多传一个环境变量给程序使用。

pif = fork();
if(pid>0)
{
    execl("/bin/ls","ls","-a","-l",NULL);
}

效果就是ls -al

char * const arg[]={"ls","-1"."-a",NULL};
execv("/bin/ls",arg);

execlp("ls","ls","-a","-l",NULL);
execvp("ls",arg);//这两组函数都是先去$PATH中找

        execle与execvpe,main函数原型不只是main(int argc,char **argv),而是main(int argc,char **argv,char **env);一个程序自带env可进行打印查看。

char *const envp[]{"AA=aaa","xx=abcd",NULL};
execle("/bin/ls","ls","-l","-a",NULL,envp);
envp会将程序中的env进程顶替,fork的子进程环境变量会被继承

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值