三:execve系统调用
int execve(const char *filename, char *const argv[],char *const envp[]);
fork创建了一个新的进程,产生一个新的PID
execve用被执行的程序完全替换了调用进程的映像。
execve启动一个新程序,替换原有进程,所以被执行进程的PID不会改变。
execve函数接受三个参数
--path 要执行的文件完整路径
--argv 传递给程序完成参数列表,包括argv[],它一般是执行程序的名字,最后一个参数一般是NULL
--envp 是指向执行execed程序的环境指针,一般设为NULL
//execve函数的定义
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h> int main(int arg, char * args[])
{
/*
第一个参数是程序的名字,第二个参数是被调用程序的参数,最后一个参数必须是NULL
这个跟main函数的参数args数组很相似
*/
char * argv[]={"/bin/ls","-l",NULL};
execve("/bin/ls",argv,NULL);
/*
execve函数是替换原来的程序代码,但是进程PID不会变,文件描述符不会变,只是程序代码被替换了
所以execve函数后面的语句都不会被执行
*/
printf("program is end!\n");
return ;
}
wait和waitpid函数可以收集子进程的退出状态
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
stauts保存子进程的退出状态(本质上就是子进程的返回值,但是我们不能直接查看这个返回值,必须用宏定义转化一下)
在waitpid函数中,参数pid是等待进程的PID,他能够接受一下四种值
"<-1" 等待任何PGID等于PID的绝对值子进程
"-" 等待任何子进程(这个进程创建的子进程)
"" 等待任何PGID等于调用进程的子进程
">0" 等待PID等于pid的子进程
//wait函数的定义
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h> int main(int arg, char * args[])
{
pid_t child=;
int status=;
child=fork();
if(child==-)
{
printf("system is game over!\n");
return -;
}
if(child==)
{
//in child process
printf("child is begining!\n");
sleep();
printf("child is end , now is your turn!\n");
}else{
//in parent process
printf("parent is begining , i am wait my son!\n");
wait(&status);
printf("child status=%d\n",WEXITSTATUS(status));
printf("my son is end , now i am go !\n");
}
printf("all is end!\n");
return ;
}

用fork或者execve函数创建一个新进程,为了收集新进程的退出状态并且防止出现僵死进程(zombie process),父进程应该调用wait或者waitpid函数等待进程终止。
僵死进程
一个僵死进程是在父进程退出之前就终止的子进程(子进程在父进程之前终止,此时因为父进程还没有退出,所以系统会保留子进程的pid,退出
状态,返回给父进程有wait函数,如果父进程没有wait函数,系统就会一直保持子进程的PID等信息,直到父进程退出)
之所以被称为僵死进程是因为他虽然死掉了,但依然在进程表中存在。
子进程退出后分配给他的内存和其他资源都被释放,但是子进程还在内核进程表保留一条,内核在父进程回收子进程的退出状态前一直保留它。
有一个两个僵死进程不算什么问题,但一旦一个程序频繁执行fork或者execv却又不能手机退出状态,那么最终将会填满进程表(内核进程表是有上限的),这会影响性能,可能导致系统重启

孤儿进程
孤儿进程是一个父进程在调用wait或者waitpid之前就已经退出了(即父进程在子进程之前退出)。此时init进程成为子进程的父进程。
init进程成为子进程的父进程,收集子进程的退出状态,从而避免出现僵死进程。
注意:任何一个进程都必须有父进程,init的父进程是0号进程,父进程与子进程是相对独立的(子进程会拷贝进程控制器和代码区,写时拷贝数据区),父进程退出,子进程不一定会退出

Linux 进程创建二(execve和wait)的更多相关文章

  1. Linux进程管理(二)

    目录 Linux进程管理(二) 参考 vmstat命令 top命令 Linux进程管理(二)

  2. Linux 进程创建一(system和fork)

    一:system系统调用 #include <stdlib.h> int system(const char *string); system函数传递给/bin/sh -c 来执行stri ...

  3. Linux进程创建和结束

    在Linux中,进程的创建由系统调用fork和vfork完成.它们生成一个子进程并且子进程是父进程的一个复制品. Fork系统调用对应的kernel函数是sys_fork,此函数简单的调用kernel ...

  4. linux进程创建

    1.  进程是程序的执行,会被加载到内存中,每个进程包括程序的代码和数据,其中数据包括程序的变量的数据,外部数据,程序堆栈. 2. Linux中,输入命令,如vi main.c 通过shell来执行, ...

  5. linux 进程创建clone、fork与vfork

    目录: 1.clone.fork与vfork介绍 2.fork说明 3.vfork说明 4.clone说明5.fork,vfork,clone的区别 内容: 1.clone.fork与vfork介绍 ...

  6. linux进程篇 (二) 进程的基本控制

    2. 进程的基本操作 接口函数 #include <unistd.h> //创建子进程 pid_t fork(void); //结束子进程 void exit(int status); / ...

  7. Linux 进程(二):进程关系及其守护进程

    进程关系 进程组 进程组是一个或多个进程的集合.通常,它们是在同一作业中结合起来的,同一进程组中的各进程接收来自同一终端的各种信号,每个进程组有一个唯一的进程组ID.每个进程组有一个组长进程,该组长进 ...

  8. linux进程(二)

    信号管理进程使用kill命令发送信号与进程通信定义守护进程的角色结束用户会话的进程 kill,killall,pgrep,pkill 对于进程的正常关闭的理解正常关闭程序的方法systemctl st ...

  9. 二十二、Linux 进程与信号---进程创建

    22.1 fork 和 vfork 函数 22.1.1 函数说明 #include <unistd.h> #include <sys/types.h> pid_t fork( ...

随机推荐

  1. MythXinWCF通用宿主绿色版发布(一键启动,方便快捷)

    这是我开发的一款免费的,绿色的WCF宿主工具,一键启动,方便快捷,省去了安装和配置IIS的麻烦,也不需要配置文件. 该工具运行环境为.Net Framework 4.5.1(这个是必装的,win10自 ...

  2. 【转载】网络攻击技术(三)——Denial Of Service & 哈希相关 & PHP语言 & Java语言

    找到了这个系列的原始作者: http://www.cnblogs.com/rush/archive/2012/02/05/2339037.html 最近网络安全成了一个焦点,除了国内明文密码的安全事件 ...

  3. C# 解决窗体假死的状态

    异步调用是CLR为开发者提供的一种重要的编程手段,它也是构建高性能.可伸缩应用程序的关键.在多核CPU越来越普及的今天,异步编程允许使用非常少的线程执行很多操作.我们通常使用异步完成许多计算型.IO型 ...

  4. socket编程演示样例(多线程)

    client代码例如以下: import java.io.*; import java.net.*; import java.util.Scanner; public class SimpleChat ...

  5. Rails时间扩展方法

    1.时间扩展方法: beginning_of_day,end_of_day等等 Time.now.end_of_day 2.ruby类型判断 is_a?(类型) 如:b.is_a?(Array)

  6. B3:状态模式 State

    当一个对象内在状态改变时允许改变其行为,这个对象看起来像是改变了其类.状态模式主要解决当控制一个对象状态转换条件表达式过于复杂时的情况,把状态判断逻辑移到表示不同状态的一系列类中.如果状态判断很简单, ...

  7. 解决apt-get的E: Could not get lock /var/lib/dpkg/lock方法

    使用apt-get进行软件的install或update时,有时会出现以下提示信息: E: Could not get lock /var/lib/dpkg/lock - open (11 Resou ...

  8. 【Python3 爬虫】07_正则表达式(原子)

    原子是正则表达式的最基本的组成单位,而且在每个模式中最少包含一个原子.原子是由所有那些未显示指定为元字符的打印和非打印字符组成. 原子分类 1.普通字符作为原子 普通字符是编写正则表达式时最常见的原子 ...

  9. 【BIEE】19_不齐整维和越级维

    不齐整维:没有子节点的维度 越级维:层级维度出现断裂,则称为越级维 下图我们就可以清晰的看出: 首先,我们将表导入到资料库做好与事实表的关联后并建立相应维 以下是按照一般维度创建维后的结果 创建完成之 ...

  10. android adt 最新下载地址

    打开这个网址就可以看到adt的详细信息:  http://developer.android.com/sdk/installing/installing-adt.html 或者直接在你的eclipse ...