您好,欢迎来到99网。
搜索
您的当前位置:首页深入理解计算机系统———fork()函数的运用

深入理解计算机系统———fork()函数的运用

来源:99网

fork()函数定义如下:

pid_t fork( void);
(pid_t 是一个宏定义,其实质是int 被定义在#include<sys/types.h>中)
返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1

函数说明

fork0

void fork0() 
{
    if (fork() == 0) {
	printf("Hello from child\n");
    }
    else {
	printf("Hello from parent\n");
    }
}

fork1

void fork1()
{
    int x = 1;
    pid_t pid = fork();

    if (pid == 0) {
	printf("Child has x = %d\n", ++x);
    } 
    else {
	printf("Parent has x = %d\n", --x);
    }
    printf("Bye from process %d with x = %d\n", getpid(), x);
}

fork2

void fork2()
{
    printf("L0\n");
    fork();
    printf("L1\n");    
    fork();
    printf("Bye\n");
}

fork3

void fork3()
{
    printf("L0\n");
    fork();
    printf("L1\n");    
    fork();
    printf("L2\n");    
    fork();
    printf("Bye\n");
}

void fork4()
{
    printf("L0\n");
    if (fork() != 0) {
	printf("L1\n");    
	if (fork() != 0) {
	    printf("L2\n");
	}
    }
    printf("Bye\n");
}

void fork5()
{
    printf("L0\n");
    if (fork() == 0) {
	printf("L1\n");    
	if (fork() == 0) {
	    printf("L2\n");
	}
    }
    printf("Bye\n");
}

void cleanup(void) {
    printf("Cleaning up\n");
}
void fork6()
{
    atexit(cleanup);
    fork();
    exit(0);
}

fork7

void fork7()
{
    if (fork() == 0) {
	/* Child */
	printf("Terminating Child, PID = %d\n", getpid());
	exit(0);
    } else {
	printf("Running Parent, PID = %d\n", getpid());
	while (1)
	    ; /* Infinite loop */
    }
}


这里,父进程并没有退出,所以导致程序一直在运行,成为僵尸(zombies.)进程,一直在后台运行,具体表现如下,无法在终端创建新程序,只有Ctrl+C或者Ctrl+Z退出此程序才可以进行新的操作。

fork8

void fork8()
{
    if (fork() == 0) {
	/* Child */
	printf("Running Child, PID = %d\n",
	       getpid());
	while (1)
	    ; /* Infinite loop */
    } else {
	printf("Terminating Parent, PID = %d\n",
	       getpid());
	exit(0);
    }
}

和前面的一样,父进程返回非0,所以输出PPID;然后进入子进程,输出PID,但是之后进入死循环,子进程并没有退出,成为僵尸进程。

fork9

void fork9()
{
    int child_status;

    if (fork() == 0) {
	printf("HC: hello from child\n");
        exit(0);
    } else {
	printf("HP: hello from parent\n");
	wait(&child_status);
	printf("CT: child has terminated\n");
    }
    printf("Bye\n");
}

这里注意一下:pid_t wait(int *status)

进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。

上述程序,父进程需在调用wait()时等待子进程结束,再执行下面的操作。


总结
1.fork 函数被调用一次,但返回两次
2.将子进程 ID 返回给父进程的理由是:一个进程的子进程可以有多个,并且没有一个函数使一个进程可以获得其所有子进程的进程 ID
3.fork 使子进程得到返回值 0 的理由是:一个进程只会有一个父进程,所以子进程可以通过调用 getppid 函数,来获得其父进程的进程 ID
4.进程 ID 0 总是由内核交换进程使用,所以一个子进程的进程 ID 不可能为 0
5.fork 之后进程的动作:子进程和父进程继续执行 fork 调用之后的指令。
6.子进程是父进程的副本。fork 之后,子进程获得父进程数据空间、堆和栈的副本。注意:这是子进程所拥有的副本。父进程和子进程并不共享这些存储空间部分。父进程和子进程共享正文段
其实创建子进程,就是把父进程的 PCB 拷贝过来,稍加修改,例如,修改子进程的进程 ID(肯定不能和父进程一样), 就变成子进程的 PCB 了。
7.进程调度:父进程和子进程谁先被执行,完全由进程调度器决定,谁先调度,是不确定的。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- 99spj.com 版权所有 湘ICP备2022005869号-5

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务