这个fork练习中使用到的一些库函数:
1) fork函数原型:
#include <unistd.h>
pid_t fork(void);
描述:
fork创建一个子进程。通过复制调用进程创建一个新进程。被称为子进程的新进程是一个调用进程完全相同的副本。
2) getpid函数原型:
pid_t getpid(void);
pid_t getppid(void);
描述:
- getpid() :返回调用这个函数的进程的进程ID(这经常由产生唯一临时文件名的程序使用)。
- getppid():返回调用进程父进程的进程ID。
3) wait函数原型:
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
这些系统调用用于等待调用进程的子进程中状态变化,并且获取状态已经变化的子进程的信息。一个状态变化被认为是:子进程终结,子进程被一个信号停止;或者执行一个等待,或者子进程由一个信号告知它继续运行。在一个被终结子进程的情况中,执行一个wait,允许系统释放与这个子进程相关联的资源;如果未执行一个wait,则被终结子进程保持"僵尸"状态。
如果一个子进程已经变化状态,则这个调用立即返回。否则,它阻塞到一个子进程发生状态变化或者一个信号处理程序中断这个调用。
扫描二维码关注公众号,回复:
14557500 查看本文章
fork.c程序源代码:
/*
fork.c展示fork函数如何使用。
编译这个源文件使用以下命令:
gcc -o fork fork.c -std=gnu99
*/
int i = 0;
/* 父进程,子进程都会调用这个函数,这个函数接收一个字符串参数,展示出谁调用它 */
void doSomeWork(char * name)
{
const int NUM_TIMES = 5;
for (; i < NUM_TIMES; i++){
sleep(rand() % 4);
printf("Done pass %d for %s\n",i,name);
}
}
int main(int argc, char * argv[])
{
printf("I am: %d\n", (int)getpid());
// 执行fork产生一个子进程,在父进程中返回子进程号,在子进程中返回0
pid_t pid = fork();
int ret;
if (pid < 0)
perror("fork failed");
else if (pid == 0) // 子进程执行的代码段,执行完括号中的语句后,子进程退出
{
printf("I am child with pid %d\n", getpid());
doSomeWork("Child");
sleep(5);
printf("Child exiting\n");
exit(8);
}
else // 父进程执行的代码段
{
printf("I am the parent\n");
}
printf("I am parent, waiting for child to end\n");
doSomeWork("Parent");
pid_t childpid = wait(&ret); // 父进程等待子进程运行终结,获取其返回状态
int childretValue = WEXITSTATUS(ret); // 获取子进程的退出状态,即exit函数的参数
printf("parent knows child %d finished with status %d\n", childpid, childretValue);
return 0;
}
编译以上命令后,执行结果如下:
[blctrl@bjAli C_Program]$ ./fork
I am: 2018
I am the parent
I am parent, waiting for child to end
I am child with pid 2019
Done pass 0 for Parent
Done pass 0 for Child
Done pass 1 for Parent
Done pass 1 for Child
Done pass 2 for Parent
Done pass 2 for Child
Done pass 3 for Parent
Done pass 3 for Child
Done pass 4 for Parent
Done pass 4 for Child
Child exiting
parent knows child 2019 finished with status 8