Linux下有四类创建子进程的函数:system() , fork() , exec*() , popen()
system函数
原型:
#include <stdlib.h>
int system(const char *string);
system函数通过调用 shell 程序 /bin/sh –c 来执行string所指定的命令,该函数在内部是通过调用execve(“/bin/sh”,..)函数来实现的。通过system创建子进程后,原进程和子进程各自运行,相互间关联较少。如果system调用成功,将返回0。
|
#include <stdio.h>
#include <stdlib.h>
int main()
{
system("ls -l"); //system(“clear”); 表示清屏
return 0;
}
|
fork函数 原型:
#include <unistd.h>
pid_t fork(void); //父进程的返回值是子进程的进程号,子进程的返回值为0。若出错则返回-1
|
在linux中fork函数是非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。它和其他函数的区别在于:它执行一次返回两个值。其中父进程的返回值是子进程的进程号,而子进程的返回值为0。若出错则返回-1。因此可以通过返回值来判断是父进程还是子进程。
fork.c | |
#include<stdio.h>
#include<unistd.h>
int main()
{
pid_t pid;
pid=fork();
if(pid==0)
{
printf("I am child,my pid=%d,my ppid=%d\n",getpid(),getppid());
while(1);
}
else
{
printf("child pid=%d\n",pid);
while(1);
}
return 0;
}
|
先返回子进程的进程号给父进程;所以先执行的else,后面接着子进程返回0,执行if语句; //不加while(1),父进程先执行,然后返回0结束,最后才执行子进程 //不加while(1) |
#include <stdlib.h>
void exit(int status); //退出进程
|
fork_stack.c | |
#include<stdio.h>
#include<unistd.h>
int main()
{
pid_t pid;
int i=3;
pid=fork();
if(pid==0)
{
i++;
printf("I am child,my pid=%d,my ppid=%d\n",getpid(),getppid());
while(1);
}
else
{
sleep(3);
printf("i=%d\n",i);
printf("child pid=%d\n",pid);
while(1);
}
return 0;
}
|
程序先进入到else,然后睡眠3s,这个时间子进程开始执行,i++,由于栈分开,不影响父进程的栈,所以最后打印的i还是3 ps -elf | grep a // 查看a开头的进程
|
fork_exit.c | |
#include<stdio.h>
#include<unistd.h>
#incldue<stdlib.h>
int main()
{
pid_t pid;
int i=3;
pid=fork();
if(pid==0)
{
i++;
printf("I am child,my pid=%d,my ppid=%d\n",getpid(),getppid());
exit(0);
}
else
{
printf("i=%d\n",i);
printf("child pid=%d\n",pid);
exit(0);
}
return 0;
}
|
//因为父进程先进入到else,exit后导致fork的子进程无法退出,卡住;查看进程,这个进程已经退出了 |
exec函数族
exec*由一组函数组成
int execl(const char *path, const char *arg, ...); //失败返回-1
int execv(const char *path, char *const argv[]); //失败返回-1
exec函数族的工作过程与fork完全不同,fork是在复制一份原进程,而exec函数是用exec的第一个参数指定的程序覆盖现有进程空间(也就是说执行exec族函数之后,它后面的所有代码不在执行)。
|
path 是包括执行文件名的全路径名(二进制文件)
arg 是可执行文件的命令行参数,多个要分割;注意最后一个参数必须为NULL表示结束。
参数:二进制文件全路径,二进制文件名,传递的参数,NULL(结束标志)
add.c | execl.c | 改写 |
#include<stdio.h>
int main(int argc,char* argv[])
{
int i=atoi(argv[1]);
int j=atoi(argv[2]);
printf("sum=%d\n",i+j);
return 0;
}
|
#include<unistd.h>
#include<stdio.h>
int main()
{
execl("./add","./add","1","2",NULL);
printf("I can not be here\n");
return -1;
}
|
#include<unistd.h>
#include<stdio.h>
int main()
{
char* argv[]={"add","1","2",NULL}
execv("./add",argv);
printf("I can not be here\n");
return -1;
}
|
popen() //创建标准流管道
2016/5/18 9:38:56讲