操作系统实验2课前说明-fork函数
福建农林大学操作系统实验报告二
福建农林大学操作系统实验报告二
《操作系统》实验报告(二)
Linux下的编程(综合性 2学时) 1、实验目的:
1) 熟悉Linux的进程机制。 2)熟悉LINUX环境编程。 2、实验内容:(1)完成LINUX系统的登录,启动终端。
(2)创建一个新用户,名为dd1。要求记录操作步骤或命令序列。
切换用户dd1
(3)进程查看命令PS的使用探讨,使用ps命令选项:-l –al ,记录命令的结果。
(4)编写一个程序,创建一个子进程,显示“New process.”子进程在休眠(15秒)后,通过调用getpid()和getppid()获取父、子进程的id后结束并退出exit()。父进程调用waitpid()等待子进程结束,并同样返回其父、子进程的id。(提示:运行过程中配合ps -l命令查看进程的家族关系。)
回答问题:当父进程不等待子进程的结束时,运行结果如何?请分析原因。运行结果:
原因:父进程执行到wait的时候,会阻塞等待子进程的结束,一个wait函数只调用一次,如果只有一个wait,其他的子进程在父进程结束后会成为孤儿进程
init进程收养。采用不阻塞方式调用waitpid的话,父进程不会等待,没执行完的子进程将会成为孤儿进程
(5)进程的创建:编制一段程序,使用系统调用fork( )创建两个子进程,在该程序运行时,在系统中就有一个父进程和两个子进程在活动。让每一个进程在屏幕上显示一个字符:父进程显示字符a,子进程分别显示字符 b和字符c。试观察、记录并分析屏幕上,进程运行的情况。(提示:运行过程中配合ps -l 命令查看进程的家族关系。)
进程的创建实验报告
进程的创建实验报告
进程的创建实验报告
引言:
在计算机科学领域中,进程是一个非常重要的概念。进程是计算机程序的执行实例,它具有独立的内存空间和执行环境。进程的创建是操作系统中一个关键的操作,本实验旨在通过编写一个简单的程序来演示进程的创建过程。
实验目的:
通过实验,我们的目标是深入理解进程的创建过程,并了解操作系统是如何管理进程的。
实验步骤:
1. 引入必要的头文件:
在开始编写代码之前,我们需要引入一些必要的头文件。这些头文件包括
<sys/types.h>、<sys/wait.h>和<unistd.h>。这些头文件提供了创建进程所需的函数和数据类型。
2. 创建一个子进程:
在主程序中,我们使用fork()函数来创建一个子进程。fork()函数会在当前进程的基础上创建一个新的进程,这个新进程称为子进程。子进程和父进程几乎完全相同,只有在返回值上有所区别。如果fork()函数返回0,表示当前进程是子进程;如果返回一个正整数,表示当前进程是父进程。
3. 子进程的执行:
在子进程中,我们可以编写任意的代码来执行特定的任务。子进程可以使用exec()函数来执行其他程序,或者执行一系列的操作。在本实验中,我们简单地
输出一条信息,以展示子进程的执行过程。
4. 父进程的执行:
在父进程中,我们可以编写代码来执行其他任务,或者等待子进程的结束。在本实验中,我们使用wait()函数来等待子进程的结束。wait()函数会暂停父进程的执行,直到子进程结束为止。
5. 编译和运行程序:
在完成代码编写后,我们需要将程序编译成可执行文件,并运行它。我们可以使用gcc编译器来编译程序,然后运行生成的可执行文件。
linux操作系统下fork函数理解
linux操作系统下fork函数理解
在Linux操作系统中,fork函数是一个非常重要的系统调用,它用于创建一个新的进程。本文将详细解释fork函数的作用、用法和实现原理,并介绍如何利用fork函数实现进程间通信以及避免一些常见的问题。
一、fork函数的作用和用法
在Linux系统中,fork函数用于创建一个新的进程,该进程是调用fork函数的进程的一个副本。具体而言,fork函数会创建一个新的进程,称为子进程,而调用fork函数的进程被称为父进程。子进程从fork函数返回的地方开始执行,而父进程则继续执行fork函数之后的代码。简单来说,fork函数的作用就是将一个进程复制成两个几乎完全相同的进程,但它们具有不同的进程ID(PID)。
fork函数的用法非常简单,只需要在程序中调用fork()即可。具体代码如下所示:
```c
#include
#include
#include
int main() {
pid_t pid = fork();
if (pid == 0) {
// 子进程代码
} else if (pid > 0) {
// 父进程代码
} else {
// fork失败的处理代码
}
return 0;
}
```
在上述代码中,首先使用pid_t类型的变量pid存储fork函数的返回值。如果pid等于0,则表示当前执行的是子进程的代码;如果pid大于0,则表示当前执行的是父进程的代码;如果pid小于0,则表示fork函数调用失败。
二、fork函数的实现原理
在Linux系统中,fork函数的实现是通过复制父进程的内存空间来创建子进程的。具体来说,fork函数会创建一个新的进程控制块(PCB),并将父进程的PCB全部复制到子进程的PCB中,包括代码段、数据段、堆栈等。由于子进程是父进程的一个副本,所以它们的代码和数据是完全相同的。
期末 操作系统实验课程设计
操作系统实验课程设计(二)(参照实验五)
学院:计算机科学与工程专业:信息管理工作与信息系统学号:2008142118 姓名:丁建东
一、实验题目:设计一个Shell解释器
二、实验目的:本设计的主要目的在于学会如何在Unix系
统下创建进程和管理进程。
三、实验内容:
实现一个简单的shell(命令行解释器),类似于bash, csh等。
要求实现的shell支持以下内部命令:
1.cd
更改当前的工作目录到另一个。如果未指定,输出当前工作目录。如果不存在,要求有适当的错误信息提示。改命令应能够改变PWD的环境变量。
2.echo
显示echo后的内容且换行。
3.help
简短概要地输出你的shell的使用方法和基本功能。
4.jobs
输出shell当前的一系列子进程,要求提供子进程的命名和PID号。
5.quit, exit, bye
退出shell。
所有的内部命令应当优于在$PATH中同名的程序。
任何非内部命令必须请求shell创建一个新进程,且该子进程执行指定的程序。这个新进程必须继承shell的环境变量和指定的命令行参数。
要求实现的shell支持以下内部命令:
Batch Processing 如果shell启动带有一个文件名作为参数,打开该文件并执行文件里所有命令。待所有进程全部结束退出shell。
四、实验思路:
1.所用到的系统函数
(1)打开目录
void cd()
API调用:int chdir(dir);getcwd(dir,dir_max);
实现:改变当前目录,并判断目录是否存在。
(2)回应
void echo()
fork函数的2个返回值说明
fork函数的2个返回值说明
fork简介:
fork英文原意是“分岔,分支”的意思,而在操作系统中,乃是著名的
Unix(或类Unix,如Linux,Minix)中用于创建子进程的系统调用。
【NOTE1】
fork () 的作用是什么,换句话说,你用 fork () 的目的是什么,
――是为了产生一个新的进程,地球人都知道 :)
产生一个什么样的进程,
――和你本来调用 fork () 的那个进程基本一样的进程,其实就是你原来进程的副本; 真的完全一样吗,
――当然不能完全一样,你要两个除了 pid 之外其它一模一样的进程干什么,就算memory 再多也不用这么摆谱吧,
哪里不一样,
――当然最重要的是 fork () 之后执行的代码不一样,you know, i know :) 怎么实现呢,
――如果是 Windows,它会让你在 fork () 里面提供一大堆东西,指明这个那个什么的…… 我用的是 unix 啊
――所以很简单,unix 会让两个进程(不错,原来是一个,unix 替你复制了一个,现在有两个)
在 fork () 之后产生不同:返回值不同。其中一个进程(使用新的 pid)里面的fork () 返回零,
这个进程就是“子进程”;而另一个进程(使用原来的 pid)中的 fork () 返回前面那个子进程的
pid,他自己被称为“父进程”
然后呢,
――写代码的人又不笨,当然就根据返回值是否非零来判断了,现在我是在子进程里面呢,还是在
父进程里面,在子进程里面就执行子进程该执行的代码,在父进程里面就执行
操作系统实验fork()
并发程序设计
【实验目的】:掌握在程序中创建新进程的方法,观察并理解多道程序并发执行的现象。
【实验原理】:fork():建立子进程。子进程得到父进程地址空间的一个复制。
返回值:成功时,该函数被调用一次,但返回两次,fork()对子
进程返回0,对父进程返回子进程标识符(非0值)。不成功时对
父进程返回-1,没有子进程。
【实验内容】:首先分析一下程序运行时其输出结果有哪几种可能性,然后实际调试该程序观察其实际输出情况,比较两者的差异,分析其中的原
因。
void main (void)
{ int x=5;
if( fork(())
{
x+=30;
printf (“%d\n”,x);
}
else
printf(“%d\n”,x);
printf((“%d\n”,x);
}
【实验要求】:每个同学必须独立完成本实验、提交实验报告、源程序和可执行程序。实验报告中必须包含预计的实验结果,关键代码的分析,
调试记录,实际的实验结果,实验结果分析等内容。
一.源程序
1.1程序.
#include<stdio.h>
#include<sys/types.h>//pid_t类型的定义
#include<unistd.h>//函数fork().getpid()定义void main (void)
{
int x=5;
if( fork( ) )
{
x+=30;
printf ("%d\n",x);
}
else
printf("%d\n",x);
printf("%d\n",x);
}
1.2预测结果:
(1)
5
5
35
35
操作系统第二次实验报告——Linux创建进程及可执行文件结构分析
操作系统第⼆次实验报告——Linux创建进程及可执⾏⽂件结构分析0 个⼈信息
张樱姿
201821121038
计算1812
1 实验⽬的
熟练Linux创建进程fork操作。
2 实验内容
在服务器上⽤VIM编写⼀个程序:⼀个进程创建两个⼦进程。
查看进程树
查看进程相关信息
3 实验报告
3.1编写程序创建两个⼦进程
1 #include<sys/types.h>
2 #include<stdio.h>
3 #include<unistd.h>
4
5int main(){
6 pid_t cpid1 = fork(); //创建⼦进程1
7
8if(cpid1<0){
9 printf("fork cd1 failed\n");
10 }
11else if(cpid1==0){
12 printf("Child1:pid: %d, ppid: %d\n",getpid(),getppid());
13 }
14else{
15 pid_t cpid2 = fork(); //创建⼦进程2
16if(cpid2<0){
17 printf("fork cd2 failed\n");
18 }
19else if(cpid2==0){
20 printf("Child2:pid: %d, ppid: %d\n",getpid(),getppid());
21 }
22else{
23 printf("Parent: pid :%d\n",getpid());
24 }
25 }
26 }
编译运⾏后的结果:
操作系统实验二(进程管理)
操作系统进程管理实验
实验题目:
(1)进程的创建编写一段程序,使用系统调用fork( )创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示字符“a”;子进程分别显示字符“b”和字符“c”。试观察记录屏幕上的显示结果,并分析原因。
(2)进程的控制修改已编写的程序,将每个进程输出一个字符改为每个进程输出一句话,在观察程序执行时屏幕上出现的现象,并分析原因。
(3)编制一段程序,使其实现进程的软中断通信。要求:使用系统调用fork( )创建两个子进程,再用系统调用signal( )让父进程捕捉键盘上来的中断信号(即按Del键);当捕捉到中断信号后,父进程调用系统调用kill( )向两个子进程发出信号,子进程捕捉到信号后分别输出下列信息后终止:Child process 1 is killed by parent! Child process 2 is killed by parent! 父进程等待两个子进程终止后,输出如下的信息后终止:Parent process is killed! 在上面的程序中增加语句signal(SIGINT, SIG_IGN)和signal(SIGQUIT, SIG_IGN),观察执行结果,并分析原因。
(4)进程的管道通信编制一段程序,实现进程的管道通信。使用系统调用pipe( )建立一条管道线;两个进程P1和P2分别向管道各写一句话:Child 1 is sending a message! Child 2 is sending a message! 而父进程则从管道中读出来自于两个子进程的信息,显示在屏幕上。要求父进程先接收子进程P1发来的消息,然后再接收子进程P2发来的消息。
fork()函数的理解
对于刚刚接触Unix/Linux
操作系统,在Linux下编写多进程的人来说,fork是最难理解的概念之一:它执行一次却返回两个值。
首先我们来看下fork函数的原型:
#i nclude
#i nclude
pid_t fork(void);
返回值:
负数:如果出错,则fork()返回-1,此时没有创建新的进程。最初的进程仍然运行。
零:在子进程中,fork()返回0
正数:在负进程中,fork()返回正的子进程的PID
其次我们来看下如何利用fork创建子进程。
创建子进程的样板代码如下所示:
pid_t child;
if((child = fork())<0)
/*错误处理*/
else if(child == 0)
/*这是新进程*/
else
/*这是最初的父进程*/
fock函数调用一次却返回两次;向父进程返回子进程的ID,向子进程中返回0,
这是因为父进程可能存在很多过子进程,所以必须通过这个返回的子进程ID来跟踪子进程,而子进程只有一个父进程,他的ID可以通过getppid取得。
下面我们来对比一下两个例子:
第一个:
#include
#include
int main()
{
pid_t pid;
int count=0;
pid = fork();
printf( "This is first time, pid = %d\n", pid );
printf( "This is sec ON d time, pid = %d\n", pid );
count++;
printf( "count = %d\n", count );
新手如何理解fork函数_华清远见
对全部高中资料试卷电气设备,在安装过程中以及安装结束后进行高中资料试卷调整试验;通电检查所有设备高中资料电试力卷保相护互装作置用调与试相技互术关,系电,力通根保1据过护生管高产线中工敷资艺设料高技试中术卷资0配不料置仅试技可卷术以要是解求指决,机吊对组顶电在层气进配设行置备继不进电规行保范空护高载高中与中资带资料负料试荷试卷下卷问高总题中体2资2配,料置而试时且卷,可调需保控要障试在各验最类;大管对限路设度习备内题进来到行确位调保。整机在使组管其高路在中敷正资设常料过工试程况卷中下安,与全要过,加度并强工且看作尽护下可关都能于可地管以缩路正小高常故中工障资作高料;中试对资卷于料连继试接电卷管保破口护坏处进范理行围高整,中核或资对者料定对试值某卷,些弯审异扁核常度与高固校中定对资盒图料位纸试置,卷.编保工写护况复层进杂防行设腐自备跨动与接处装地理置线,高弯尤中曲其资半要料径避试标免卷高错调等误试,高方要中案求资,技料编术试写5交、卷重底电保要。气护设管设装备线备置4高敷、调动中设电试作资技气高,料术课中并3试、中件资且卷管包中料拒试路含调试绝验敷线试卷动方设槽技作案技、术,以术管来及架避系等免统多不启项必动方要方式高案,中;为资对解料整决试套高卷启中突动语然过文停程电机中气。高课因中件此资中,料管电试壁力卷薄高电、中气接资设口料备不试进严卷行等保调问护试题装工,置作合调并理试且利技进用术行管,过线要关敷求运设电行技力高术保中。护资线装料缆置试敷做卷设到技原准术则确指:灵导在活。分。对线对于盒于调处差试,动过当保程不护中同装高电置中压高资回中料路资试交料卷叉试技时卷术,调问应试题采技,用术作金是为属指调隔发试板电人进机员行一,隔变需开压要处器在理组事;在前同发掌一生握线内图槽部纸内 故资,障料强时、电,设回需备路要制须进造同行厂时外家切部出断电具习源高题高中电中资源资料,料试线试卷缆卷试敷切验设除报完从告毕而与,采相要用关进高技行中术检资资查料料和试,检卷并测主且处要了理保解。护现装场置设。备高中资料试卷布置情况与有关高中资料试卷电气系统接线等情况,然后根据规范与规程规定,制定设备调试高中资料试卷方案。
操作系统实验报告
操作系统实验报告
实验项⽬⼆进程管理
⼀、实验⽬的
1.理解进程的概念,掌握⽗、⼦进程创建的⽅法。
2.认识和了解并发执⾏的实质,掌握进程的并发及同步操作。⼆、实验内容
1.编写⼀C语⾔程序,实现在程序运⾏时通过系统调⽤fork( )创建两个⼦进程,使⽗、⼦三进程并发执⾏,⽗亲进程执⾏时屏幕显⽰“I am father”,⼉⼦进程执⾏时屏幕显⽰“I am son”,⼥⼉进程执⾏时屏幕显⽰“I am daughter”。
2.多次连续反复运⾏这个程序,观察屏幕显⽰结果的顺序,直⾄出现不⼀样的情况为⽌。记下这种情况,试简单分析其原因。
3.修改程序,在⽗、⼦进程中分别使⽤wait()、exit()等系统调⽤“实现”其同步推进,并获取⼦进程的ID号及结束状态值。
多次反复运⾏改进后的程序,观察并记录运⾏结果。
三、源程序及运⾏结果
源程序1:
#include
#include
#include
int main(int argc, char ** argv )
{
int pid=fork();
if(pid < 0)
printf("error!");
else if( pid == 0 )
{
printf("I am son!\n");
}
else
{
int pid=fork();
if (pid < 0)
printf("error!");
else if( pid == 0 )
{
printf(“I am daughter! \n");
}
else
printf("I am father!\n");
}
sleep(1);
return 0;
进程的创建、执行和终止实验操作系统实验
进程的创建、执⾏和终⽌实验操作系统实验
进程的创建、执⾏和终⽌实验
⽬的:本实验的⽬的是通过使⽤Linux的系统调⽤fork()、exec()、exit()编写⼀个程序,加深理解进程的创建、执⾏和终⽌等内容。
内容:
(1)利⽤fork()函数创建两个⼦进程。让系统中的3个进程分别输出⼀个不同的字符。观察并记录屏幕上显⽰的结果,分析原因。
(2)利⽤fork()和execlp()函数实验⼀个shell的基本功能,如图所⽰。⽤户输⼊命令后,按下列步骤执⾏⽤户命令:
1:利⽤fork()函数创建⼀个⼦进程。
2:利⽤execlp()函数启动命令程序。
3:利⽤wait()函数使⽗进程和⼦进程同步。
第⼀题代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
pid_t pid_1 = fork();
pid_t pid_2 = fork();
if (pid_1 == 0)
{
printf("我是⼦进程⼀号\t进程号是:%d\n", getpid());
exit(0);
}
if (pid_2 == 0)
{
printf("我是⼦进程⼆号\t进程号是:%d\n", getpid());
exit(0);
}
if (pid_1 != 0 && pid_2 != 0)
{
printf("我是⽗进程\t进程号是:%d\n", getpid());
}
}
运⾏结果:
第⼆题代码:
#include <stdio.h>
操作系统上机实验报告
操作系统上机实验报告
计算机科学与技术学院
操作系统上机实验报告
实验名称:
进程和线程
实验⽬的:
理解unix/Linux下进程和线程的创建、并发执⾏过程。
实验内容:
1.进程的创建
2.多线程应⽤
实验步骤:
⼀、进程的创建
下⾯这个C程序展⽰了UNIX系统中⽗进程创建⼦进程及各⾃分开活动的情况。
1、实验指导
fork( )
创建⼀个新进程。
系统调⽤格式:
pid=fork( )
参数定义:
int fork( )
fork( )返回值意义如下:
0:在⼦进程中,pid变量保存的fork( )返回值为0,表⽰当前进程是⼦进程。
>0:在⽗进程中,pid变量保存的fork( )返回值为⼦进程的id值(进程唯⼀标识符)。
-1:创建失败。
如果fork( )调⽤成功,它向⽗进程返回⼦进程的PID,并向⼦进程返回0,即fork( )被调⽤了⼀次,但返回了两次。此时OS在内存中建⽴⼀个新进程,所建的新进程是调⽤fork( )⽗进程(parent process)的副本,称为⼦进程(child process)。⼦进程继承了⽗进程的许多特性,并具有与⽗进程完全相同的⽤户级上下⽂。⽗进程与⼦进程并发执⾏。
2、参考程序代码
/*process.c*/
#include
#include
main(int argc,char *argv[])
{
int pid;
/* fork another process */
pid = fork();
if (pid < 0) { /* error occurred */
fprintf(stderr, "Fork Failed");
操作系统实验2——进程控制
实验2 进程控制
一、实验目的
加深对进程概念的理解,明确进程和程序和区别;进一步认识并发执行的实质;分析进程争用资源的现象。
二、实验内容
1. 熟悉Linux进程控制常用命令。
2. 输入进程创建、控制的程序并调试程序。
三、实验预备知识
1. 进程控制常用命令
(1)ps 命令
功能:查看目前的系统中有哪些进程,以及它们的执行情况。
常用命令格式及功能如下:
ps 查看系统中属于自己的进程
ps au 查看系统中所有用户的进程
ps aux 查看系统中包含系统内部的及所有用户的进程
主要输出列说明:
USER:进程所有者的用户名
PID:进程号
TTY:进程从哪个终端启动
TIME:此进程所消耗的CPU时间
COMMAND:正在执行的命令或进程名称
(2)top 命令
功能:动态显示进程,实时监测进程状态。与ps命令相似,只是top命令在执行后会以指定的时间间隔来刷新显示信息,以使top所显示的进程状态总是当前时刻的。
(3)kill 命令
功能:结束或终止进程。
常用命令格式及功能如下:
kill 5302 杀死PID为5302的进程
kill -9 5302 强行杀死PID为5302的进程
(4)echo $变量名
功能:查看外壳变量的设定值。
例:echo $$ 显示当前进程PID
2.常用系统调用函数
常用系统调用函数、程序的说明、参数及定义如下:
(1)fork()函数
功能:创建一个新进程
函数格式:int fork()
其中返回int取值意义如下:
小于0:创建失败
0: 创建成功,在子进程中返回0值
大于0: 创建成功,在父进程中返回子进程id值
操作系统实验---进程的创建与控制
实验报告
实验题目
姓名:
学号:
课程名称:操作系统实验
所在学院:信息科学与工程学院
专业班级:计算机
任课教师:
核心为fork( )完成以下操作:
(1)为新进程分配一进程表项和进程标识符
进入fork( )后,核心检查系统是否有足够的资源来建立一个新进程。若资源不足,则fork( )系统调用失败;否则,核心为新进程分配一进程表项和唯一的进程标识符。
(2)检查同时运行的进程数目超过预先规定的最大数目时,fork( )系统调用失败。(3)拷贝进程表项中的数据将父进程的当前目录和所有已打开的数据拷贝到子进程表项中,并置进程的状态为“创建”状态。
(4)子进程继承父进程的所有文件对父进程当前目录和所有已打开的文件表项中的引用计数加1。
(5)为子进程创建进程上、下文进程创建结束,设子进程状态为“内存中就绪”并返回子进程的标识符。
(6)子进程执行虽然父进程与子进程程序完全相同,但每个进程都有自己的程序计数器PC(注意子进程的注意子进程的PC 开始位置),然后根据pid 变量保存的fork( )返回值的不同,执行了不同的分支语句。
四、实验过程、步骤及内容
1、编写一段程序,使用系统调用fork( )创建两个子进程。当此程序运行时,在
系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示'a',子进程分别显示字符'b'和字符'c'。试观察记录屏幕上的显示结果,并分析原因。
2、修改上述程序,每一个进程循环显示一句话。子进程显示'daughter …'及
'son ……',父进程显示'parent ……',观察结果,分析原因。
fork实现原理
fork实现原理
Fork 实现原理
在操作系统中,fork 是基本的进程创建操作之一,它会复制当前进程
的所有资源创建出一个新的进程。在本文中,我们将探讨 fork 的实
现原理。
1. fork 函数
在 Unix 系统中,fork 的实现是通过系统调用来完成的。用户程序调
用 fork 函数之后,系统内核(kernel)会复制一份当前进程的所有资
源并创建出一个新的进程,这个新的进程也称为子进程。在父进程中,fork 函数会返回子进程的 PID(process ID),而在子进程中,它会返
回 0。
2. 内存结构
在 fork 函数被调用的时候,操作系统会将当前进程的虚拟地址空间
复制一份给子进程。这样,子进程就有了自己的独立内存空间,可以
与父进程并行执行。
注意,这里只是指虚拟地址空间,物理内存并没有被复制。操作系统
会使用写时复制(Copy-on-write)技术,即在子进程需要修改内存中某
个值时才会开辟新的物理内存空间,避免了大量的内存复制。这种技
术可以大大提高程序的运行效率。
3. 文件描述符和文件表
文件描述符是一个整数,用来标识一个特定的文件或资源。在 Unix
系统中,每一个进程都有属于自己的文件表,其中存储了打开的文件列表以及文件的各种元信息。
在 fork 操作中,子进程会继承父进程的全部文件描述符和文件表。这意味着在子进程中打开或关闭文件等操作都会影响父进程的文件,相当于父子进程共享文件。
4. 进程控制块
进程控制块(Proc Control Block,PCB)是操作系统内部维护的一个数据结构,存储了进程的各种属性。在 fork 后,子进程会获取一份父进程的 PCB,包括进程 ID、状态、优先级等信息。这使得系统可以在同一个进程中对父子进程进行管理和调度。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
关于fork函数的多进程编程研究
首先我们来看一下多进程的使用,我们简单的使用fork函数来实现。第一步:我们man fork一下,发现它所依赖的头文件是:sys/types.h 和unistd.h好吧,于是我们开始来使用它。
代码一:
#include
#include
#include
main()
{pid_t pid; //pid_t 类型实际上就是int型
pid = fork();
if(pid < 0)
printf("erro \n");
else if(pid == 0){
printf("child \n");
}
else{
printf("parnts \n");
}}
这个就是最简单的fork使用了,编译一下,输出:
[xdyang@SEP4020 learning]$ ./fork
child
parnts
好了,大家就要开始问了,为什么会这样?同样一个if的判断语句,为什么会要进去两次?其实很简单,这个我们今天这段代码所要实现的功能:多进程。当一个进程调用fork函数后,就会创建一个子进程,子进程会拷贝(见附录二)父进程的代码段,但是拥有自己的数据段。也就是说,其实我们调用了fork函数后,相当于把这个函数代码复制了一遍,也就是产生了类似下面这样的代码:
#include
#include
#include
main(){
//进程一
pid_t pid;
pid = fork();
if(pid < 0)
printf("erro \n"); else if(pid == 0){ printf("child \n"); }
else{
printf("parnts \n"); }
//进程二
if(pid < 0)
printf("erro \n"); else if(pid == 0){ printf("child \n"); }
else{
printf("parnts \n"); }
}
好了,这样你就可以理解为什么会有两次的if判断了吧,然而,随机而来的问题就是为什么两次if判断的pid的值是不一样的?其实这就是fork的精髓了,就是所谓的一个fork返回两个值,我是这样理解的,在进程一中,它的返回值为0,那么没有问题,它会打印child,在进入进程二之后,它会再次赋值 (见附录一),这时,它就会被赋值为父进程的ID,就会去打印parents了,当然究竟是先被赋值为0还是先被赋值为父进程的ID,这个是由系统的调用算法所决定。
好了,最基本的东西大家都可以理解了,在上面我们提到说两个进程的数据区是不一样,那我们用下面的这个代码来做个试验
代码二:
#include
#include
#include
main(){
int i = 0;
pid_t pid;
pid = fork();
if(pid < 0)
printf("erro \n");
else if(pid == 0){
i++;
printf("child is %d\n", i);
}
else{
i++;
printf("parnts is %d\n", i);
}
}
这个函数的编译后面的执行结果就是:
[xdyang@SEP4020 learning]$ ./fork
child is 1
parnts is 1
我们发现,尽管在上面子进程中执行了i++的操作,父进程中的i值并没有变化,这就证明了两者的数据区其实是不在的一起的。
好了,理解了上面两点基本上就理解fork的用法,但是在仍然有人遇到了这样一个问题,代码如下:
代码三:
#include
#include
#include
main(){
int i = 0;
pid_t pid;
printf("fork");//与代码二相比较多的代码
pid = fork();
if(pid < 0)
printf("erro \n");
else if(pid == 0){
i++;
printf("child is %d\n", i);
}
else{
i++;
printf("parnts is %d\n", i);
}
}
我们预计的打印结果应该是:
forkchild is 1
parnts is 1
然而,事实无情地告诉我们,结果不是这样的,执行结果如下:
[xdyang@SEP4020 learning]$ ./fork
forkchild is 1
forkparnts is 1
fork竟然被打印了两次,这如何解释,难道说在调用fork之前的代码也会执行两次,难道说我们刚刚的理解是错误的,其实不然,我们又看下面这段代码:
代码四:
#include
#include
#include
main(){
int i = 0;
pid_t pid;
printf("fork\n");//注意与代码三的差别
pid = fork();
if(pid < 0)
printf("erro \n");
else if(pid == 0){
i++;
printf("child is %d\n", i);
}
else{
i++;
printf("parnts is %d\n", i);