linux中fork同时创建多个子进程的方法(一)

linux中fork同时创建多个子进程的方法(一)
linux中fork同时创建多个子进程的方法(一)

fork函数和子进程

Fork函数 函数pid_t fork(void) 正确返回:在父进程中返回子进程的进程号,在子进程中返回0 错误返回:-1 子进程是父进程的一个拷贝。即,子进程从父进程得到了数据段和堆栈段的拷贝,这些需要分配新的内存;而对于只读的代码段,通常使用共享内存的方式访问。fork返回后,子进程和父进程都从调用fork函数的下一条语句开始执行。父进程与子进程的不同之处在于:fork的返回值不同——父进程中的返回值为子进程的进程号,而子进程为0。 以下是fork的两个示例程序: //fork.c #include #include void main () { int pid; //printf("Process [%d] begin",getpid()); //print twice printf("Process [%d] begin\n",getpid()); //print once //由于fork时pc等值的拷贝,子进程只会从fork处开始执行 pid = fork(); if (pid < 0) printf("error in fork!"); else if (pid == 0) printf("I'm child process, my pid is %d\n", getpid()); else printf("I'm parent process, my pid is %d\n", getpid()); printf("Process [%d] end\n",getpid()); return; } 输出结果: 使用printf("Process [%d] begin\n",getpid())时 Process [11155] begin I'm parent process, my pid is 11155

惠州学院操作系统进程的创建与并发执行实验(精编文档).doc

【最新整理,下载后即可编辑】 实验一进程的创建与并发执行 一、实验目的: (1) 熟悉Linux工作环境、文本编辑器工具和GCC工具 (2) 加深对进程概念的理解,明确进程和程序的区别 (3) 进一步认识并发进程的实质和特征 二、实验仪器及材料: 微型计算机、Linux系统 三、实验内容: 1、任务1:进程创建 编写一段程序,让父进程产生两个子进程,父进程显示字符“a”、两个子进程,分别显示字符“b”、“c”。 任务2:将上述的输出字符改为输出较长的字符串,观察进程并发执行,分析执行结果。 2、源代码: 任务1: #include main(){ int p1, p2; while ((p1=fork())==-1); /*父进程创建第一个进程,直到成功*/ if (p1==0) /*0返回给子进程1*/ printf(“b\n”); /*P1的处理过程*/ else/*正数返回给父进程(子进程号)*/ { while ((p2=fork())==-1); /*父进程创建第二个进程,直到成功*/ if (p2==0) /* 0返回给子进程2*/ printf(“c\n”); /*P2的处理过程*/ else printf(“a\n”); /*P2创建完成后,父进程的处理过程*/

} } 任务2: #include main(){ int p1, p2; while ((p1=fork())==-1); /*父进程创建第一个进程,直到成功*/ if(p1==0) while (1) printf(“A ”) else { while ((p2=fork())==-1); /*父进程创建第二个进程,直到成功*/ if (p2==0) while (1) printf(“B ”) else /*P2创建完成后,父进程的处理过程*/ while (1) printf(“P ”); } } 四、实验结果记录: 任务1:

操作系统实验2课前说明-fork函数

关于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"); } }

进程的创建与并发执行-带答案版课案

实验二进程管理 2.1 进程的创建与并发执行 1.实验目的 (1) 加深对进程概念的理解,理解进程和程序的区别。 (2) 认识并发进程的实质。分析进程争用资源的现象,学习解决进程互斥的方法。 (3) 理解系统调用和用户命令的区别。 2.实验类型:验证型 3.实验学时:2 4.实验原理和知识点 (1) 实验原理:程序的并发执行具有随机性和不可再现性。程序并发执行会导致资源共享和资源竞争,各程序向前执行的速度会受资源共享的制约。程序的动态执行过程用进程这个概念来描述。由于向前推进的速度不可预知,所以多个进程并发地重复执行,整体上得到的结果可能不同。但要注意,就其中某单个进程而言,其多次运行结果是确定的。 (2) 知识点:进程、子进程、并发执行的特性; 5.实验环境(硬件环境、软件环境): (1)硬件环境:Intel Pentium III 以上CPU,128MB以上内存,2GB以上硬盘 (2)软件环境:linux操作系统。 6. 预备知识 (1) fork()系统调用 头文件:#include unix standard header /*是POSIX标准定义的unix类系统定义符号常量的头文件,包含了许多UNIX系统服务的函数原型,例如read函数、write函数和getpid函数*/ 函数原型: pid_t fork(void); /*是Linux下的进程号类型,也就是Process ID _ Type 的缩写。其实是宏定义的unsigned int类型*/ 函数功能:fork的功能是创建子进程。调用fork的进程称为父进程。如图2.1所示。子进程是父进程的一个拷贝,它继承了父进程的用户代码、组代码、环境变量、已打开的文件代码、工作目录及资源限制。fork语句执行后,内核向父进程返回子进程的进程号,向子进程返回0。父子进程都从fork()的下一句开始并发执行。 返回值: 返回值==-1:创建失败。 返回值==0:程序在子进程中。 返回值>0:程序在父进程中。(该返回值是子进程的进程号) 编程提示:虽然子进程是父进程的一个复制品,但父子的行为是不同的。编程时要抓住内核的返回值。通过返回值,可以知道是父进程还是子进程,因而可以编写不同行为的代码。

fork函数实验总结

针对fork函数难以理解,根据网上的解释,参考他人代码,做了如下实验,并附以实验分析 2 #include 3 #include 4 #include 5 #include 6 #include 7 8 int main () 9 { 10 pid_t pc,pr; 11 pc=fork(); (gdb) 12 13 if (pc<0) 14 { 15 printf("error fork.\n"); 16 17 } 18 else if (pc==0) 19 { 20 printf("this is pc=%d\n",getpid()); 21 sleep(5); (gdb) 22 printf("5 s over\n"); 23 //exit(0); 24 } 25 pr=fork(); 26 if (pr==0) 27 { 28 printf("this is pr =%d\n",getpid()); 29 } 30 31 else if (pr>0&&pc>0) (gdb) 32 printf("this is main =%d",getpid()); 33 34 35 36 37 38 } (gdb) b 12

Breakpoint 1 at 0x804849d: file /home/lsp/fork3.c, line 12. (gdb) b 19 Breakpoint 2 at 0x80484b7: file /home/lsp/fork3.c, line 19. (gdb) b 24 Breakpoint 3 at 0x80484e4: file /home/lsp/fork3.c, line 24. (gdb) b 26 Breakpoint 4 at 0x80484ec: file /home/lsp/fork3.c, line 26. (gdb) run Starting program: /home/lsp/fork3 Detaching after fork from child process 13200. ---说明pc=fork()函数已经建立子进程 this is pc=13200 Breakpoint 1, main () at /home/lsp/fork3.c:13 13 if (pc<0) (gdb) 5 s over this is pr =13201 --说明pc=fork()进程13200启动了新的子进程pr 其pid=13201 next Breakpoint 3, main () at /home/lsp/fork3.c:25 25 pr=fork(); --父进程停在pr=fork()处, (gdb) next Detaching after fork from child process 13254. this is pr =13254 --此处pr的pid=13254 与上一个pr=13201不同,这说明此处的pr是由main创建的 Breakpoint 4, main () at /home/lsp/fork3.c:26 26 if (pr==0) (gdb) next 31 else if (pr>0&&pc>0) (gdb) next 32 printf("this is main =%d",getpid()); (gdb) next 38 } (gdb) next 0x00a6d5d6 in __libc_start_main () from /lib/libc.so.6 (gdb) next Single stepping until exit from function __libc_start_main, which has no line number information. this is main =13199 ---main函数退出,器pid=13199 Program exited with code 023. (gdb)

操作系统课程设计并发进程的模拟

课程设计说明书题目: 并发进程的模拟 院系:计算机科学与工程 专业班级: 学号: 学生姓名: 指导教师: 2014年 11月 12 日

安徽理工大学课程设计(论文)任务书 2014年11月21日

安徽理工大学课程设计(论文)成绩评定表 I

目录 1问题描述 0 2需求分析 0 3概要设计 (1) 1. P操作 (1) 2. V操作 (2) 3. P,V操作实现进程同步 (3) 4. 功能模块设计 (4) 4详细设计 (6) 1.主界面的设计程序 (6) 2.进程Pa的执行 (7) 3.进程Pb的执行 (8) 4.进程Pc的执行 (8) 5.按钮的执行 (9) 5 调试的分析与运行结果 (10) 6 设计体会 (12) 参考文献 (13)

1问题描述 在进程并发执行的过程中,进程之间存在协作的关系,例如,有互斥、同步的关系。该课程设计的是了解进程同步的概念,理解信号量机制的原理,掌握运用信号量解决进程并发控制问题的方法,进而学会运用进程的同步,利用信号灯的P,V操作实现三个进程的同步。这三个进程的同步关系如下: 从上图中可以看出:任务启动后pa先执行,当它结束后,pb、pc可以开始执行,pb、pc 都执行完毕后,任务终止;设两个同步信号灯sb、sc分别表示进程pb和pc能否开始执行,其初值均为0。 在现代操作系统中,有大量的并发进程在活动,它们都处在不断的申请资源,使用资源以及其它进程的相互制约的活动中,这些进程什么时候停止运行,什么时候该继续向前推进,应根据事先的约定来规范它们的行为,这时我们可以根据同步信号灯来实现进程的同步协调工作。例如本题中,只有pa进程顺利的进行完,Pb,Pc这两个进程才能正常的进行。如果进程Pa在进行中出现停止或中断,则Pb和Pc是不会顺利的完成的;而进程Pb,Pc这两个进程是并行执行的,两个进程的进行是互不干扰的,只要进程Pa完成后,进程Pb和Pc才会正常执行,否则只有处在等待就绪中。 2需求分析 进程执行的并发性的意义是关于一组进程的执行在是时间上是重叠的,从宏观上看,并发性反应的是一个时间段中几个进程都在同一个处理器上,处于运行还未运行结束状态。从微观上看,任何一个时刻仅有一个进程在处理器上运行。并发的实质是一个处理器在几个进程之间的多路复用,并发是对有限的物理资源强制行驶多用户共享,消除计算机部件之间的乎等现象,以提高系统资源利用率。

进程创建之fork系统调用

4 进程创建 (1) 4.1 实验内容及要求 (1) 4.2 实验目的 (1) 4.3 实验环境 (1) 4.4 实验思路 (1) 4.5 实验代码 (2) 4.6 运行结果 (3) 4.7 实验心得 (3) 4 进程创建 4.1 实验内容及要求 利用fork()系统调用创建进程。要求如下: 编制一段程序,使用系统调用fork( )创建两个子进程,这样在此程序运行时,在系统中就有一个父进程和两个子进程在活动。每一个进程在屏幕上显示一个字符,其中父进程显示字符A,子进程分别显示字符 B和字符C。试观察、记录并分析屏幕上进程调度的情况。 4.2 实验目的 了解进程的创建过程,进一步理解进程的概念,明确进程和程序的区别。 4.3 实验环境 Ubuntu 18.04.1 LTS 64位,编译器gcc 7.3.0 (Ubuntu 7.3.0-16ubuntu3) 4.4 实验思路 (1)可用fork()系统调用来创建一个新进程。 系统调用格式:pid=fork() fork()返回值意义如下: =0:若返回值为0,表示当前进程是子进程。 >0:若返回值大于0,表示当前进程是父进程,返回值为子进程的pid值。

<0:若返回值小于0,表示进程创建失败。 如果fork()调用成功,它向父进程返回子进程的pid,并向子进程返回0,即fork()被调用了一次,但返回了两次。此时OS在内存中建立一个新进程,所建的新进程是调用fork()父进程的副本,称为子进程。子进程继承了父进程的许多特性,并具有与父进程完全相同的用户级上下文。父进程与子进程并发执行。 (2)编译和执行的方法: 编译:在shell提示符下输入gcc 源文件名 -o 可执行文件名 运行:在shell提示符下输入 ./可执行文件名 4.5 实验代码 #include #include #include int main(void) { pid_t p1=fork();pid_t p2=fork(); //迭代调用fork(),创建三个新进程printf("this is parent, pid = %d\n", getpid()); //父进程 if(p1<0||p2<0){ //fork()失败 printf("fork failed with p1=%d, p2=%d\n", p1, p2); exit(1); }if(p1==0&&p2==0){ //子进程B创建的子进程D,即孙进程 printf("D in grandson Damson, pid = %d\n", getpid()); }if(p1==0&&p2>0){ //父进程创建的子进程B printf("B in child Blueberry, pid = %d\n", getpid()); }if(p1>0&&p2==0){ //父进程创建的子进程C printf("C in child Carambola, pid = %d\n", getpid()); }if(p1>0&&p2>0){ //父进程 printf("A in parent Apple, pid = %d\n", getpid()); }return 0; }

Linux的fork、exec、wait函数的分析

Linux 的fork 、exec 、wait 函数分析 I 数学与计算机学院 课程设计说明书 课 程 名 称: 操作系统原理-课程设计 课 程 代 码: 8404061 题 目: Linux 的fork 、exec 、wait 函数的分析 年级/专业/班: 学 生 姓 名: 学 号: 3 开 始 时 间: 2010 年 12 月 12 日 完 成 时 间: 2011 年 01 月 09 日 课程设计成绩: 指导教师签名: 年 月 日

Linux 的fork 、exec 、wait 函数分析 II 目 录 1 引 言 ................................................................. 1 1.1 问题的提出 ...................................................................................................................... 1 1.2国内外研究的现状 ........................................................................................................... 1 1.3任务与分析 ....................................................................................................................... 1 2代码分析结果 ............................................................ 2 2.1 数据结构 ......................................................................................................................... 2 2.1.1 struct task_struct ............................................................................................. 2 2.1.2 task ......................................................................................................................... 3 2.1.3 tarray_freelist ................................................................................................... 3 2.1.4 struct--linux_binprm ......................................................................................... 3 2.1.5进程状态 .................................................................................................................. 4 2.2常量和出错信息的意义 .................................................................................................. 4 2.3调用关系图 ...................................................................................................................... 4 2.4各模块/函数的功能及详细框图 .................................................................................... 5 2.4.1 do_fork 模块 .......................................................................................................... 5 2.4.2 get_pid 模块 .......................................................................................................... 8 2.4.3 do_execve 模块 ........................................................................................................ 10 3.4.4 do_exit 模块 ........................................................................................................ 14 3.4.5 sys_wait4模块 .................................................................................................. 18 3 总结与体会 ............................................................ 20 4 参考文献 .. (20)

最新Linux多进程并发执行实验

一、实验目的 1 2 1、对理论课中学习的进程、程序等的概念作进一步的理解,明确进程和程序3 的区别; 2、加深理解进程并发执行的概念,认识多进程并发执行的实质; 4 5 3、观察进程争夺资源的现象,分析其过程和原因,学习解决进程互斥的方法;6 4、对经典的多用户、多任务的优先级轮转调度系统Linux有一定的了解; 7 5、了解Linux系统中多进程之间通过管道通信的基本原理和应用方法。 8 9 二、实验内容 10 1、用virtual虚拟机运行linux虚拟系统; 11 2、分析并理解源程序; 12 3、在linux中输入相应程序并观察运行结果。 13 14 三、实验原理 15 (一)多进程并发执行是使用后台任务来实现任务的“多进程化”。在不加控16 制的模式下,不管有多少任务,全部都后台执行。也就是说,在这种情况下,有17 多少任务就有多少“进程”在同时执行。 18 (二)实验中要用到的函数 19 1、fork()函数——进程创建函数。

2、getpid()函数——取得目前进程的进程标识码。 20 21 3、exit()函数——用来正常终结目前进程的执行。 22 4、sleep()函数——用来延时,它会被挂起,把处理器让给其他的进程。 23 5、printf()函数——是格式化输出函数, 一般用于向标准输出设备按规24 定格式输出信息。 25 (三)实验中要用的命令 1、cd 命令: 26 27 功能:改变工作目录。 28 语法:cd [directory] 说明:该命令将当前目录改变至directory所指定的目录。若没有指定 29 30 directory,则回到用户的主目录。为了改变到指定目录,用户必须拥有对指定31 目录的执行和读权限。该命令可以使用通配符。 32 2、mkdir命令: 33 功能:创建一个目录(类似MSDOS下的md命令)。 34 语法:mkdir [选项] dir-name 35 说明:该命令创建由dir-name命名的目录。要求创建目录的用户在当前目录36 中(dir-name的父目录中)具有写权限,并且dirname不能是当前目录中已有37 的目录或文件名称。 38 3、ls 命令: 功能:ls是英文单词list的简写,其功能为列出目录的内容。这是用户最常 39 40 用的一个命令之一,因为用户需要不时地查看某个目录的内容。该命令类似于

fork函数

fork函数 在linux中,只有一个函数可以创建子进程:fork。 #include #include pid_t fork(void); 由f o r k创建的新进程被称为子进程(child process)。该函数被调用一次,但返回两次。两次返回的区别是子进程的返回值是0,而父进程的返回值则是新子进程的进程I D。将子进程I D返回给父进程的理由是:因为一个进程的子进程可以多于一个,所以没有一个函数使一个进程可以获得其所有子进程的进程I D。f o r k使子进程得到返回值0的理由是:一个进程只会有一个父进程,所以子进程总是可以调用g e t p p i d以获得其父进程的进程I D (进程ID 0总是由交换进程使用,所以一个子进程的进程I D不可能为0 )。 子进程和父进程共享很多资源,除了打开文件之外,很多父进程的其他性质也由子进程继承: ? 实际用户I D、实际组I D、有效用户I D、有效组I D。 ? 添加组I D。 ? 进程组I D。 ? 对话期I D。 ? 控制终端。 ? 设置-用户- I D标志和设置-组- I D标志。 ? 当前工作目录。 ? 根目录。 ? 文件方式创建屏蔽字。 ? 信号屏蔽和排列。 ? 对任一打开文件描述符的在执行时关闭标志。 ? 环境。 ? 连接的共享存储段。 ? 资源限制。 父、子进程之间的区别是: ? fork的返回值。

? 进程I D。 ? 不同的父进程I D。 ? 子进程的t m s _ u t i m e , t m s _ s t i m e , t m s _ c u t i m e以及t m s _ u s t i m e设置为0。 ? 父进程设置的锁,子进程不继承。 ? 子进程的未决告警被清除。 ? 子进程的未决信号集设置为空集。 使f o r k失败的两个主要原因是:( a )系统中已经有了太多的进程(通常意味着某个方面出了问题),或者( b )该实际用户I D的进程总数超过了系统限制。回忆表2 - 7,其中C H I L D _ M A X规定了每个实际用户I D在任一时刻可具有的最大进程数。 f o r k有两种用法: (1) 一个父进程希望复制自己,使父、子进程同时执行不同的代码段。这在 网络服务进程中是常见的——父进程等待委托者的服务请求。当这种请求到达时,父进程调用f o r k,使子进程处理此请求。父进程则继续等待下一个服务请求。 (2) 一个进程要执行一个不同的程序。这对s h e l l是常见的情况。在这种情 况下,子进程在从f o r k返回后立即调用e x e c。 我们从一个例子程序中可以看到fork函数的作用,子进程与父进程之间的资源共享。

Linux C 中vfork和fork的区别

Linux C 中vfork和fork的区别 我们知道, fork会创建一个新的进程,这个新的进程是当前进程的子进程,区别在于, fork函数会复制父进程的一些资源,也就是,仅仅是复制的关系,而非共享。而vfork就不同了,利用vfork创建的子进程和父进程共享地址空间,下面,我们通过实际程序来看看: 1、fork函数的简单应用: #include #include #include int main() { int a = 0; pid_t pid; pid = fork(); if(pid < 0) { printf("error\n"); return -1; } else if(0 == pid) { printf("child\n"); printf("%d\n" a); } else { a = 1;

printf("parent\n"); printf("%d\n" a); } return 0; } 运行一下,结果为: parent 1 child 由此可见,父进程值的修改,不会影响到子进程,为什么呢?因为他们没有共享地址空间啊。 2、我们再看看vfork: #include #include #include int main() { int a = 0; pid_t pid; pid = vfork(); if(pid < 0) { printf("error\n"); return -1;

} else if(0 == pid) { a = 1; printf("child\n"); printf("%d\n" a); _exit(0); // 这个先不管它,以后再说 } else { printf("parent\n"); printf("%d\n" a); } return 0; } 结果为: child 1 parent 1 可见, vfork创建的子进程和父进程确实共享着内存空间呢。

fock()函数问题

#include #include #include int main() { pid_t pid1; pid_t pid2; pid1 = fork(); pid2 = fork(); printf("pid1:%d, pid2:%d\n", pid1, pid2); } 输出: pid1:3411, pid2:3412 pid1:0, pid2:3413 pid1:3411, pid2:0 pid1:0, pid2:0 1. 基础知识: 1)fork函数总是“调用一次,返回两次”,在父进程中调用一次,在父进程和子进程中各返回一次。fork在子进程中的返回值是0,而在父进程中的返回值则是子进程的id。 2)子进程在创建的时候会复制父进程的当前状态(PCB信息相同,用户态代码和数据也相同)。 3)程序运行的结果基本上是父子进程交替打印,但这也不是一定的,取决于系统中其它进程的运行情况和内核的调度算法。 2. 第一个fork: 子进程A被创建,之后从fork函数往下执行与父进程相同的代码,即后一个fork和printf 会被父进程和子进程A分别执行一次: 父进程打印的pid1和pid2是两个子进程的pid,即结果的第一行:pid1:3411, pid2:3412 子进程A打印的pid1和pid2是这个fork在子进程A中的返回(0)和子进程A中调用fork返回的pid,即结果的第二行:pid1:0, pid2:3413 3. 第二个fork: 这个fork会被父进程和子进程A都执行一遍。假设子进程B被主进程创建,子进程C被子进程A创建。子进程A也可以说是子进程C的父进程,为了避免混淆,我这里改叫主进程而不再使用父进程的概念。 子进程B的打印即结果的第三行:pid1:3411, pid2:0。其中,其中,pid1为复制的主进程的数据,pid2为该fork在子进程B中的返回。 子进程C的打印,即结果的最后一行:pid1:0, pid2:0。其中,pid1为复制的进程A的数据,pid2为该fork在子进程C内部的返回。

新手如何理解fork函数_华清远见

新手如何理解fork函数 我想,刚接触fork函数的时候,很多人都无法完全理解他,新手就更不用说了,为了让大家能正确理解fork函数,所以就写了一篇关于新手如何理解fork函数的文章。 首先我们来看看,什么是fork函数:计算机程序设计中的分叉函数。返回值:若成功调用一次则返回两个值,子进程返回0,父进程返回子进程标记;否则,出错返回-1。fork函数将运行着的程序分成2个(几乎)完全一样的进程,每个进程都启动一个从代码的同一位置开始执行的线程。这两个进程中的线程继续执行,就像是两个用户同时启动了该应用程序的两个副本。 正题开始了,对于刚刚接触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_tpid; int count=0; pid = fork(); printf( "This is first time, pid = %d\n", pid ); printf( "This is second time, pid = %d\n", pid ); count++; printf( "count = %d\n", count ); if ( pid>0 ) { printf( "This is the parent process,the child has the pid:%d\n", pid ); } else if ( !pid ) { printf( "This is the child process.\n") }

进程管理习题及答案

第二章进程管理习题及答案 一、填空题 1.进程的静态描述由三部分组成:① 、② 和③ 。 【答案】①PCB、②程序部分、③相关的数据结构集 【解析】PCB是系统感知进程的唯一实体。进程的程序部分描述了进程所要 完成的功能,而数据结构集是程序在执行时必不可少的工作区和操作对象。后两 部分是进程完成所需功能的物质基础。 2.进程存在的标志是。 【答案】进程控制块PCB 【解析】系统根据PCB感知进程的存在和通过PCB中所包含的各项变量的变化,掌握进程所处的状态以达到控制进程活动的目的。 3.① 是现代操作系统的基本特征之一,为了更好地描述这一特征而 引入了 ② 这一概念。 【答案】①程序的并发执行,②进程 【解析】程序的并发执行和资源共享是现代操行系统的基本特征。程序的并 发执行使程序失去了程序顺序执行时所具有的封闭性和可再现性。在程序并发执 行时,程序这个概念不能反映程序并发执行所具有的特性,所以引入进程概念来 描述程序并发执行所具有的特点。 4.给出用于进程控制的四种常见的原语① 、② 、③ 和④ 。【答案】①创建原语、②撤消原语、③阻塞原语、④唤醒原语 【解析】进程控制是系统使用一些具有特定功能的程序段来创建、撤消进程 以及完成进程各状态间的转换,从而达到多个过程高效率地并行执行和协调,实 现资源共享的目的。把那些在管态下执行的具有特定功能的程序段称为原语。 5.进程被创建后,最初处于① 状态,然后经② 选中后进入③ 状态。 【答案】①就绪,②进程调度程序,③运行 【解析】进程的从无到有,从存在到消亡是由进程创建原语和撤消原语完成的。被创建的进程最初处于就绪状态,即该进程获得了除处理机以外的所有资源,处于准备执行的状态;从就绪状态到运行状态的转换是由进程调度程序来完成的。 6.进程调度的方式通常有① 和② 方式两种。 【答案】①可剥夺、②非剥夺 【解析】所谓可剥夺方式,是指就绪队列中一旦有优先级高于当前运行进程 的优先级的进程存在时,便立即发生进程调度,转让处理机。而非剥夺方式则是指:即使在就绪队列中存在有优先级高于当前运行进程的进程,当前进程仍将继 续占有处理机,直到该进程完成或某种事件发生(如I/O事件)让出处理机。 7.轮转法主要是用于① 的调度算法,它具有较好的② 时间, 且对每个进程来说都具有较好的③ 性。 【答案】①分时系统②响应③公平 【解析】所谓轮转调度算法,就是将CPU的处理时间分成固定的时间片,处 于就绪状态的进程按一定的方式(如先到先服务FCFS)排成一个队列,该队列

fork系统调用

fork系统调用 (1) fork系统调用说明 fork系统调用用于从已存在进程中创建一个新进程,新进程称为子进程,而原进程称为父进程。fork调用一次,返回两次,这两个返回分别带回它们各自的返回值,其中在父进程中的返回值是子进程的进程号,而子进程中的返回值则返回 0。因此,可以通过返回值来判定该进程是父进程还是子进程。 使用fork函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空间,包括进程上下文、进程堆栈、内存信息、打开的文件描述符、信号控制设定、进程优先级、进程组号、当前工作目录、根目录、资源限制、控制终端等,而子进程所独有的只有它的进程号、计时器等。因此可以看出,使用fork系统调用的代价是很大的,它复制了父进程中的数据段和堆栈段里的绝大部分内容,使得fork系统调用的执行速度并不很快。 fork的返回值这样设计是有原因的,fork在子进程中返回0,子进程仍可以调用getpid函数得到自己的进程ID,也可以调用getppid函数得到父进程的进程ID。在父进程中使用getpid函数可以得到自己的进程ID,然而要想得到子进程的进程ID,只有将fork的返回值记录下来,别无它法。 fork的另一个特性是所有由父进程打开的文件描述符都被复制到子进程中。父、子进程中相同编号的文件描述符在内核中指向同一个file结构体,也就是说,file结构体的引用计数要增加。 由于代码段(加载到内存的执行码)在内存中是只读的,所以父子进程可共用代码段,而数据段和堆栈段子进程则完全从父进程复制拷贝了一份。 (2)父进程进行fork系统调用时完成的操作 假设id=fork(),父进程进行fork系统调用时,fork所做工作如下: ①为新进程分配task_struct任务结构体内存空间。 ②把父进程task_struct任务结构体复制到子进程task_struct任务 结构体。 ③为新进程在其内存上建立内核堆栈。 ④对子进程task_struct任务结构体中部分变量进行初始化设置。 ⑤把父进程的有关信息复制给子进程,建立共享关系。 ⑥把子进程加入到可运行队列中。 ⑦结束fork()函数,返回子进程ID值给父进程中栈段变量id。 ⑧当子进程开始运行时,操作系统返回0给子进程中栈段变量id。(3)fork调用时所发生的事情

fork函数详解

一、fork入门知识 一个进程,包括代码、数据和分配给进程的资源。fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。 一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。 我们来看一个例子: /* * fork_test.c * version 1 * Created on: 2010-5-29 * Author: wangth */ #include #include int main () { pid_t fpid; //fpid表示fork函数返回的值 int count=0; fpid=fork(); if (fpid < 0) printf("error in fork!"); else if (fpid == 0) { printf("i am the child process, my process id is %d\n",getpid()); printf("我是爹的儿子\n");//对某些人来说中文看着更直白。 count++; } else { printf("i am the parent process, my process id is %d\n",getpid()); printf("我是孩子他爹\n"); count++; } printf("统计结果是: %d\n",count); return 0; } 运行结果是: i am the child process, my process id is 5574 我是爹的儿子 统计结果是: 1 i am the parent process, my process id is 5573

相关文档
最新文档