进程之多个子进程
- 创建子进程一,在子进程中递归打印/home目录中的内容(可以用exec系列函数调用第一次实验中的代码完成此功能);
- 子进程退出的时候调用cpexit()函数,在cpexit()函数中完成以下功能:
打印字符串“Child process exited!”打印子进程标识符,打印父进程标识符。
- 创建子进程二, 打印子进程运行环境中环境变量“USER”的值,通过exec系列中的某个函数设置子进程”USER”环境变量值为“zhangsan”,并且让该子进程同时完成以下命令:“ls –li /home”.*/
#include <stdio.h>
#include <stdlib.h> //编译这个文件时,先 要把遍历目录的程序 编译
#include <string.h> //例如 :gcc bianli.c -o text (这个是编译遍历目录的程序 这个text一定要和代码中说的那个“./text”相同)
#include <sys/types.h> // gcc jinchengbianli.c -o test (这个是编译这个程序)
#include <unistd.h> // ./test (运行这个实验)
void cpexit () //登记函数
{
printf ("child process exited! \n");
printf ("child's pid : %d \n father's pid : %d \n",getpid(),getppid()); //"getpid()"打印子进程id ,getppid()打印父进程id
}
int main()
{
int pid1,pid2;
pid1 = fork(); //创建子进程 1
if (pid1 == 0) //如果pid1为 0 ,那就是子进程
{ //这个peng,需要改动,打开你的终端在@ubuntu或者@redhat 前面写的什么,把这个peng就该成什么
execl("/home/peng/text","./text",NULL); //作用是递归打印/home目录中的内容,实现方式是:需要先编译前面写的那个遍历目录的程序《gcc bianli.c -o text》 “bianli.c”这是我遍历目录的程序名字,你跟据你的那个程序名字来编译,“text” 这个是可执行文件,这个要和“./text”保持一致(意思就是如果gcc * * * x,那么就是“./x”) "./text"这是直接找到编译完成之后的文件(text)然后执行这个文件。
printf ("child's pid : %d \n",getpid());
atexit (cpexit); //调用登记函数,“cpexit”这个就是登记的函数
exit (0); //退出子进程 1
}
pid2 = fork(); //创建子进程 2
if (pid2 == 0) //判断是否为子进程
{
char *argv[] = {"ls","-li","/home",NULL}; //这个数组储存的命令是,查看home下的内容
char *argc[] = {"USER = zhangsan",NULL}; //这个数组储存的命令是:给USER这个环境变量赋值为 zhangsan,
printf ("USER这个环境变量的值为:%s \n",getenv ("USER")); //打印USER这个环境变量的值
execve ("/bin/ls",argv,argc); //“/bin”是一个函数库,ls 命令在这个库函数中存放,这行代码实现的就是argv这个数组里面的命令,
printf ("%s \n",getenv ("USER")); //虽然这次输出环境变量的值,但是并没有输出,因为在execve里面只是执行了第一个的/bin/ls操作,并且在里面出不来了
exit (0);//退出子进程 2
}
return 0;
}
- 登记函数里面打印出来的子进程id和在子进程中打印出来的是否一样? 是一样的
- 登记函数什么时候调用的 ?
在子进程结束前调用的 在子进程结束前调用的
- execve中第二个数组为什么没有执行?
exec函数族的函数执行成功后不会返回,因为调用进程的实体,包括代码段,数据段和堆栈等都已经被新的内容取代,exec函数族的函数执行成功后不会返回,因为调用进程的实体,包括代码段,数据段和堆栈等都已经被新的内容取代,