(本节笔记接上一节的进程控制,继续学习多进程的程序设计函数,详细的实验代码在这里)
1. 创建进程
函数名:
fork
函数原型:
pid_t fork ( void );
函数功能:
创建一个子进程
所属头文件:
<unistd.h>
返回值:
成功:在父进程中返回子进程的pid,在子进程中返回0 失败:返回1
参数说明:
void
范例代码:(touch myfork.c)
#include <unistd.h>
#include <stdio.h>
int main(int argc, char ** argv)
{
fork();
printf("Program is end!\n");
exit(0);
}
输出结果:Program is end!
Program is end!
分析:当父进程调用fork创建一个代码与父进程一样的子进程是,子进程由printf开始执行!(重要)
pid的返回值代码:
#include <unistd.h>
#include <stdio.h>
int main(int argc, char ** argv)
{
pid_t pid = fork();
printf("pid is %d!\n");
exit(0);
}
输出结果:pid is 19112!
pid is 0
让父进程执行分支的方法:
#include <unistd.h>
#include <stdio.h>
int main(int argc, char ** argv)
{
pid_t pid = fork();
if ( pid > 0) /* parent process */
{
printf("here is parent process!\n");
}
else /* child process */
{
printf("here is child process.\n");
}
exit(0);
}
2. 创建进程的另一种方式
函数名:
vfork
函数原型:
pid_t vfork ( void );
函数功能:
创建一个子进程,并阻塞父进程
所属头文件:
<sys/types.h> <unistd.h>
返回值:
成功:在父进程返回子进程的ID,在子进程返回0
参数说明:
void
范例代码:(touch myvfork.c)
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main ( int argc, char ** argv)
{
pid_t pid = vfork();
if ( pid > 0)
{
printf("father\n");
exit(0);
}
else
{
printf("child\n);
exit(0);
}
}
程序输出的结果:child
father
分析——fork与fork的区别:vfork会阻塞父进程,子进程优先运行,而fork的父子进程的运行顺序是随机的
范例代码2:(touch forkcount.c)
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main ( int argc, char ** argv)
{
int count = 0;
pid_t pid = vfork();
count++;
printf("%d\n", count);
exit(0);
}
程序输出的结果:1
1
分析——在调用fork()创建的子进程中的栈是完全复制了父进程的栈,而且与父进程的栈相互独立。而vfork()创建的子进程与父进程共享同一个栈。
3. 进程的退出
父进程:可用return 0 , 也可用exit(0);
子进程:只能使用exit(0);
4. 进程等待
函数名:
wait
函数原型:
pid_t wait ( int *status);
函数功能:
挂起调用它的进程,直到其子进程结束
所属头文件:
<sys/types.h> <sys/wait.h>
返回值:
成功:返回中止的那个进程的PID 失败:返回-1
参数说明:
status:记录子进程的退出状态。
范例代码:(touch mywait.c)
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
int main( int argc, char ** argv)
{
pid_t pid = fork();
if ( pid > 0)
{
wait ( NULL );
printf( "father\n");
exit(0);
}
else
{
printf("child\n");
exit(0);
}
}
4. 程序执行
函数名:(execl、execv、execle、execve、execlp、execvp)
execl
函数原型:
int execl ( const char *path, const char *arg, ...);
函数功能:
运行可执行文件
所属头文件:
<unistd.h>
返回值:
成功:无返回 失败:返回-1 (关于execl的返回值问题,可参考以下这里)
参数说明:
path:要运行的可执行程序的路径
arg:作为该可执行程序的参数,直接以NULL为参数结束标志
范例代码:
..........
execl("/bin/ls", "ls", "/home", NULL);
..........
(一旦调用了execl(),原进程代码段将被execl创建的可执行程序锁替换,例如以下两行代码:
execl(......);
printf(......);
printf的操作始终不会被执行)