进程相关函数------>fork exec函数族 exit/_exit wait/waitpid
1.fork
作用:创建一个子进程
(创建方式:子进程复制了父进程的所有的内容,他和父进程的进程号不同)
pid_t fork(void);
无入参
返回值:创建失败 ,-1
创建成功 0或pid(0->子进程 子进程的进程号-->父进程)
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
pid_t pid=-1;
printf("hello nihao!!!!!\r\n");
pid = fork();
if(-1 == pid)
{
return -1;
}
if(0 == pid)//child process
{
printf("child process,pid=%d,parent pid=%d\r\n",getpid(),getppid());
}
else//pid > 0 parent process
{
printf("parent process,parent pid=%d,pid=%d\r\n",getpid(),pid);
}
printf("hello word!!!!!!!\r\n");
return 0;
}
孤儿进程:父进程先于子进程退出,子进程由init进程收养,此时子进程就是孤儿进程,pstree查看。孤儿进程可单独存在,没有危害。
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
pid_t pid=-1;
printf("hello nihao!!!!!\r\n");
pid = fork();
if(-1 == pid)
{
return -1;
}
if(0 == pid)//child process
{
sleep(10);
printf("child process,pid=%d,parent pid=%d\r\n",getpid(),getppid());
}
else//pid > 0 parent process
{
printf("parent process,parent pid=%d,pid=%d\r\n",getpid(),pid);
}
printf("hello word!!!!!!!\r\n");
return 0;
}
僵尸进程: 子进程先于父进程退出,父进程未处理子进程的退出状态,导致该子进程成为一个僵尸进程,僵尸进程占用一个task_struct但是没有相应的地址空间,它会统一参与操作系统的调度,会消耗系统资源,对系统有危害,我们应该避免僵尸进程的产生。ps -aux查看
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
pid_t pid=-1;
printf("hello nihao!!!!!\r\n");
pid = fork();
if(-1 == pid)
{
return -1;
}
if(0 == pid)//child process
{
printf("child process,pid=%d,parent pid=%d\r\n",getpid(),getppid());
}
else//pid > 0 parent process
{
sleep(10);
printf("parent process,parent pid=%d,pid=%d\r\n",getpid(),pid);
}
printf("hello word!!!!!!!\r\n");
return 0;
}
2.exec函数族--->替换进程(在一个进程中启动另外一个进程,另外这个进程使用这个进程的所有资源)
有6个函数,作用相同,传参方式不同。传参方式由 l v p e组合而成
l:lis以列表的方式传参,最后以NULL结束。
v:vector以数组方式传参,数组的最后一个元素为NULL。
e:env环境变量,传参方式同数组。
p:PATH,在PATH所指的路径中去找可执行程序。
#include<stdio.h>
int main()
{
printf("hello!!!!!!!\r\n");
if(-1 == execlp("ls","ls","-l",NULL))
{
printf("execlp error!!!!!!!\r\n");
return -1;
}
printf("hello world!!!!!!!/r/n");
return 0;
}
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char *argv[],char *env[])
{
while(argc--)
{
printf("%s\r\n",*argv++);
}
prrintf("..........................\r\n");
while(*env)
{
printf("%s\r\n",*env++);
}
printf("###########################\r\n");
printf("%s\r\n",getenv("PWD"));
return 0;
}
#include<stdio.h>
#include<unistd.h>
int main()
{
char *argv[]={"aaa","bbb","ccc",NULL};
char *env[]={"PWD=23456test","jiayou",NULL};
if(-1 == execve("test",argv,env))
{
printf("execve error!!!!!!!!!!!\r\n");
return -1;
}
return 0;
}
3.exit/_exit
exit:退出当前进程,并刷新IO缓冲区
参数1:表示退出状态值。0表示正常退出,其他为异常退出。
_exit:退出当前进程,不会刷新IO缓冲区
#include<stdio.h>
#include<stdlib.h>
int main()
{
printf("hello test by@23456---");
// return 0;
exit(0);
}
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
printf("hello test by@23456---");
// return 0;
// exit(0);
_exit(0);
}
4.wait/waitpid
wait:等待子进程退出(任意子进程),接收子进程的退出状态值。
pid_t wait(int *status);
*status:指向等到子进程的退出状态值的指针
返回值: >0 等到的子进程的pid
-1出错
注意:wait是一个阻塞函数
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
int main()
{
pid_t pid = -1;
pid = fork();
if(-1 == pid)
{
retuen -1;
}
if(0 == pid)
{
printf("child process pid=%d\r\n",getpid());
sleep(5);
exit(3);
}
else
{
printf("parent process,pid=%d\r\n",getpid());
int status = -1;
pid_t pidTmp = wait(&status);
printf("pidTmp=%d,status=%d\r\n",pidTmp,WEXITSTATUS(status));
sleep(10);
}
}
waitpid:等待指定子进程的退出状态值,接收子进程的退出状态值。
pid_t waitpid(pid_t pid,int *status,int options);
pid:指定子进程的pid
*status:指向等到的子进程的退出状态值的指针
options:0将waitpid函数变成了阻塞函数
WNOHANG:将waitpid函数变成了非阻塞函数,若等到结果,返回等到子进程的pid,若未等到结果,返回0.
返回值:未等到结果,返回0;等到结果,返回等到的指定子进程的pid
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
int main()
{
pid_t pid = -1;
pid = fork();
if(-1 == pid)
{
retuen -1;
}
if(0 == pid)
{
printf("child process pid=%d\r\n",getpid());
sleep(5);
exit(3);
}
else
{
printf("parent process,pid=%d\r\n",getpid());
int status = -1;
// pid_t pidTmp = wait(&status);
pid_t pidTmp = -1;
while(0 == (pidTmp = waitpid(pid,&status,WNOHANG)))
{
printf("hello test!!!!!!!!!!!!!!!!\r\n");
sleep(1);
}
printf("pidTmp=%d,status=%d\r\n",pidTmp,WEXITSTATUS(status));
sleep(10);
}
}
阻塞函数:未等到结果,不返回,会一直阻塞当前进程,直到等到结果再返回。
非阻塞函数:未等到结果,也返回,不影响当前进程的执行,通过多次循环调用,非阻塞函数去等结果。