对fork函数理解

头文件: #include <unistd.h>

pid_t fork (void);

1. 创建一个子进程,失败返回-1。

2. 调用一次,返回两次。分别在父子进程中返回子进程的PID和0。利用返回值的不同,可以分别为父子进程编写不同的处理分支。
#include <stdio.h>
#include <unistd.h>

int main (void) {
	printf ("%u进程:我要调用fork()了...\n", getpid ());

	pid_t pid = fork ();
	if (pid == -1) {
		perror ("fork");
		return -1;
	}

	if (pid == 0) {
		printf ("%u进程:我是%u进程的子进程。\n", getpid (),
			getppid ());
		return 0;
	}

	printf ("%u进程:我是%u进程的父进程。\n", getpid (), pid);
	sleep (1);

	return 0;
}

3. 子进程是父进程的副本,子进程获得父进程数据段和堆栈段(包括I/O流缓冲区)的拷贝,但子进程共享父进程的代码段。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int global = 100;

int main (void) {
	int local = 200;
	char* heap = (char*)malloc (256 * sizeof (char));
	sprintf (heap, "ABC");
	printf ("父进程:%d %d %s\n", global, local, heap);
	pid_t pid = fork ();
	if (pid == -1) {
		perror ("fork");
		return -1;
	}

	if (pid == 0) {
		global++;
		local++;
		sprintf (heap, "XYZ");
		printf ("子进程:%d %d %s\n", global, local, heap);
		free (heap);

		return 0;
	}

	sleep (1);
	printf ("父进程:%d %d %s\n", global, local, heap);
	free (heap);

	return 0;
}


#include <stdio.h>
#include <unistd.h>

int main (void) {
	printf ("ABC");

	pid_t pid = fork ();
	if (pid == -1) {
		perror ("fork");
		return -1;
	}

	if (pid == 0) {
		printf ("XYZ\n");
		return 0;
	}

	sleep (1);
	printf ("\n");

	return 0;
}
第一行输出ABCXYZ,第二行输出ABC

4. 函数调用后父子进程各自继续运行,其先后顺序不确定。某些实现可以保证子进程先被调度。
#include <stdio.h>
#include <unistd.h>

int main (void) {
	printf ("父进程:");
	int a, b, c;
	scanf ("%d%d%d", &a, &b, &c);

	pid_t pid = fork ();
	if (pid == -1) {
		perror ("fork");
		return -1;
	}

	if (pid == 0) {
		scanf ("%d%d%d", &a, &b, &c);
		printf ("子进程:%d %d %d\n", a, b, c);

		return 0;
	}

	sleep (1);
	printf ("父进程:%d %d %d\n", a, b, c);

	return 0;
}

5. 函数调用后,  父进程的文件描述符表(进程级)也会被复制到子进程中,二者共享同一个文件表(内核级)。
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

int main (void) {
	int fd = open ("ftab.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
	if (fd == -1) {
		perror ("open");
		return -1;
	}

	const char* text = "Hello, World !";
	if (write (fd, text, strlen (text) * sizeof (text[0])) == -1) {
		perror ("write");
		return -1;
	}

	pid_t pid = fork ();
	if (pid == -1) {
		perror ("fork");
		return -1;
	}

	if (pid == 0) {
		if (lseek (fd, -7, SEEK_CUR) == -1) {
			perror ("lseek");
			return -1;
		}

		close (fd);
		return 0;
	}

	sleep (1);
	text = "Linux";
	if (write (fd, text, strlen (text) * sizeof (text[0])) == -1) {
		perror ("write");
		return -1;
	}
	close (fd);
	return 0;
}
结果:Hello ,Linux !

6. 总进程数或实际用户ID所拥有的进程数, 超过系统限制,该函数将失败。

7. 一个进程如果希望创建自己的副本并执行同一份代码,或希望与另一个程序并发地运行,都可以使用该函数。

注意:fork之前的代码只有父进程执行,fork之后的代码父子进程都有机会执行, 受代码逻辑的控制而进入不同分支。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值