进程
程序就是你编译过后产生的那个文件,进程就是打开程序过后产生的。
fork |
vfork |
exit |
execl |
system |
popen |
孤儿进程 |
僵尸进程 |
wait |
fork1 |
|
|
getpid/getppid区别
pid_t getpid(void);
brief:getpid是获取当前进程的pid
param:调用getpid(),即可显示当前进程的pid
return:返回一个当前进程pid
pid_t getppid(void);
brief:getppid是获取父进程的pid
param:调用getppid(),即可显示父进程的pid
return:返回一个父进程pid
fork创建子进程
pid_t fork(void);
brief:返回两个参数,>0返回的是父进程(返回子进程的pid,把父进程的内容拷贝一份,给子进程)=0返回的是子进程
我们无法知道是父进程先运行,还是子进程先运行,我们得用到wait()函数进行堵塞
return:返回两个参数,>0父进程,=0子进程
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
void main()
{
pid_t pid;//定义的类型是进程号的类型
pid = fork();
if(pid > 0)
{
printf("this is father!\n");
printf("father pid: %d\n",getppid());
}
if(pid == 0)
{
printf("this is my son!\n");
printf("son pid:%d\n",getpid());
}
}
输出结果:
this is father!
father pid: 2694
this is my son!
son pid:6259
vfor创建子进程
pid_t vfork(void);
brief:创建子进程,但是它会让子进程先执行(直到调用exit结束后,父进程才运行),并且子进程共享内存空间
param:调用vfork(),创建子进程
return:>0返回父进程,=0返回子进程
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
void main()
{
pid_t pid;
int data = 0;
pid = vfork();
if(pid > 0)
{
printf("this is father!\n");
printf("father pid: %d\n",getpid());
}
if(pid == 0)
{ while(1)
{
printf("this is my son!\n");
data++;
if(data == 3)
{
break;
}
}
printf("son pid:%d\n",getpid());
exit(0);
}
}
输出结果:
this is my son!
this is my son!
this is my son!
son pid:7637
this is father!
father pid: 7636
僵尸进程:即子进程先于父进程终止,父进程没有wait子进程,僵尸进程变会占用过多得系统资源
孤儿进程:即父进程先于子进程终止,子进程没有father,就会派init来收留子进程,此时子进程pid = 1,子进程只是被回收了,所以并不会占用系统资源
wait函数
pid_t wait(int *wstatus);
brief:等待子进程结束,回收子进程,可以接收子进程退出状态是正常退出,还是异常退出
param:wstatus,你只想回收子进程,就写NULL,你如果想看子进程退出状态就在定义一个status,传给wstatus,接收子进程退出状态,但此时需要一个宏来解析wstatus,WEXITSTATUS,这个宏来解析子进程退出码,如果你exit(5)退出,那解析出来就=5,=0则是异常退出
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
void main()
{
pid_t pid;
int status;
pid = fork();
if(pid > 0)
{
//wait(NULL);//如果你只是想回收进程,可以直接写NULL
wait(&status);
printf("get son status: %d\n",WEXITSTATUS(status));
printf("this si father!\n");
}
if(pid == 0)
{
printf("this is my son!\n");
printf("son pid:%d\n",getpid());
exit(1);
}
}
输出结果:
this is my son!
son pid:8085
get son status: 1
this si father!
execl/stytem/popen函数
int execl(const char *path, const char arg, / (char *) NULL */)
brief: 在进程或子进程里面替换子进程所拷贝得代码段、数据段、堆栈..从而执行execl里面得命令,但是调用execl,它后面得内容就不会被执行
param:path,执行命令得绝对路径,arg,给这个命令取个名字,后面得arg,则是参数
return:执行成功不返回,执行失败返回-1
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
void main()
{
pid_t pid;
pid = fork();
if(pid > 0)
{
wait(NULL);
printf("this is father\n");
}
if(pid == 0)
{
printf("this is my son\n");
execl("/mnt/hgfs/learn/hallo","hallo",NULL);
printf("Allen iverson");
}
}
输出结果:
this is my son
This is Li jian hua
this is father
int system(const char *command);
brief:跟execl函数一样,但是它执行完system过后,后面得代码可以继续执行
param:command,即要执行命令的绝对路径
return:执行失败返回127,其他原因返回-1
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
void main()
{
pid_t pid;
pid = fork();
if(pid > 0)
{
wait(NULL);
printf("this is father\n");
}
if(pid == 0)
{
printf("this is my son\n");
system("/mnt/hgfs/learn/hallo");
printf("Allen iverson\n");
}
}
输出结果:
this is my son
This is Li jian hua
Allen iverson
this is father
FILE *popen(const char *command, const char *type);
brief:跟execl/system一样,但是它执行完popen可以继续执行其他代码,并且可以把执行的命令给保存下来
param:command,执行命令的绝对路径,type,"w" 把这个文件流从管道输出, "r"把这个文件流流向管道,我们用fread来读取
return:返回一个文件指针
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
void main()
{
pid_t pid;
FILE * fd;
char readbuf[1024]= {0};
pid = fork();
if(pid > 0)
{
wait(NULL);
printf("this is father\n");
}
if(pid == 0)
{
printf("this is my son\n");
fd = popen("/mnt/hgfs/learn/hallo","r");//"r",读取
fread(readbuf,1,1024,fd);
printf("readbuf = %s\n",readbuf);
exit
}
}
输出结果:
this is my son
readbuf = This is Li jian hua
this is father