fork函数学习笔记

本文探讨了进程的概念以及fork函数在创建新进程中的作用。通过csapp的描述,了解到进程是执行中的程序实例,每次运行程序都会创建新进程。fork函数创建子进程,子进程拥有父进程的地址空间副本,但具有独立PID。调用fork一次,但在父进程和子进程中分别返回子进程ID和0,以此区分执行环境。文章通过不同参数的fork示例,借助进程图帮助理解并发执行和地址空间的独立性。
摘要由CSDN通过智能技术生成

学习fork函数,首先要了解进程的含义。
csapp上说:进程是计算机科学中最深刻、最成功的概念之一。进程的经典定义就是一个执行中的程序的实例。系统中的每个程序都运行在某个进程的上下文(context)中。上下文是由程序正确运行所需的状态组成的。这个状态包括存放在内存中的程序的代码和数据,它的栈、通用目的寄存器的内容、程序计数器、环境变量以及打开文件描述符的集合。
每次用户通过向shell输入一个可执行目标文件的名字,运行程序时,shell就会创建一个新的进程,然后在这个新的进程的上下文中运行这个可执行目标文件。应用程序也能够创建新进程,并且在这个新进程的上下文中运行他们自己的代码或其它应用程序。

父进程通过调用fork函数创建一个新的运行的子进程。新创建的子进程几乎但不完全与父进程相同。子进程得到与父进程用户级虚拟地址空间相同的(但独立的)一份副本,包括代码和数据段、堆、共享库以及用户栈。子进程还获得与父进程中打开文件描述符相同的副本,这就意味着当父进程调用fork时,子进程可以读写父进程中打开的任何文件。父进程和新创建的子进程之间最大的区别在于他们有不同的PID。
fork函数只被调用一次,却会返回两次:一次是在父进程中,一次是子进程中。在父进程中,fork返回子进程的PID。在子进程中,fork返回0。因为子进程的PID总是为非零,返回值就提供一个明确的方法来分辨程序是在父进程还是在子进程中执行。
简而言之,fork的四个特点分别是:调用一次,返回两次;并发执行;相同但是独立的地址空间;共享文件。

接下来先查看一下18种不同的fork:

/*
 * forks.c - Examples of Unix process control
 */
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h> 
#include <signal.h>
/*
 * fork0 - The simplest fork example
 * Call once, return twice
 * Creates child that is identical to parent
 * Returns 0 to child process
 * Returns child PID to parent process
 Hello from parent
 Hello from child
 */
void fork0() 
{
   
    if (fork() == 0) {
   
	printf("Hello from child\n");
    }
    else {
   
	printf("Hello from parent\n");
    }
}
/* 
 * fork1 - Simple fork example 
 * Parent and child both run same code
 * Child starts with identical private state
 Parent has x = 0
Bye from process 2629 with x = 0
 Child has x = 2
Bye from process 2630 with x = 2
 */
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 - Two consecutive forks
 * Both parent and child can continue forking
 * Ordering undetermined
L0
L1
Bye
$ Bye
L1
Bye
Bye
 */
void fork2()
{
   
    printf("L0\n");
    fork();
    printf("L1\n");    
    fork();
    printf("Bye\n");
}
/*
 * fork3 - Three consective forks
 * Parent and child can continue forking
 L0
L1
L2
Bye
$ Bye
L2
Bye
L1
L2
Bye
Bye
Bye
L2
Bye
Bye
 */
void fork3()
{
   
    printf("L0\n");
    fork();
    printf("L1\n");    
    fork();
    printf("L2\n");    
    fork();
    printf("Bye\n");
}
/* 
 * fork4 - Nested forks in parents
 L0
L1
L2
Bye
$ Bye
Bye
 */
void fork4()
{
   
    printf("L0\n");
    if (fork() != 0) {
   
	printf("L1\n");    
	if (fork() != 0) {
   
	    printf("L2\n");
	}
    }
    printf("Bye\n");
}
/*
 * fork5 - Nested forks in children
 L0
Bye
$ L1
Bye
L2
Bye
 */
void fork5()
{
   
    printf("L0\n");
    if (fork() == 0) {
   
	printf("L1\n");    
	if (fork() == 0) {
   
	    printf("L2\n");
	}
    }
    printf("Bye\n");
}
void cleanup(
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值