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

关于fork函数的多进程编程研究首先我们来看一下多进程的使用,我们简单的使用fork函数来实现。
第一步:我们man fork一下,发现它所依赖的头文件是:sys/types.h 和unistd.h好吧,于是我们开始来使用它。
代码一:#include <stdio.h>#include <sys/types.h>#include <unistd.h>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]$ ./forkchildparnts好了,大家就要开始问了,为什么会这样?同样一个if的判断语句,为什么会要进去两次?其实很简单,这个我们今天这段代码所要实现的功能:多进程。
当一个进程调用fork函数后,就会创建一个子进程,子进程会拷贝(见附录二)父进程的代码段,但是拥有自己的数据段。
也就是说,其实我们调用了fork函数后,相当于把这个函数代码复制了一遍,也就是产生了类似下面这样的代码:#include <stdio.h>#include <sys/types.h>#include <unistd.h>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,这个是由系统的调用算法所决定。
进程的创建实验报告

进程的创建实验报告进程的创建实验报告引言:在计算机科学领域中,进程是一个非常重要的概念。
进程是计算机程序的执行实例,它具有独立的内存空间和执行环境。
进程的创建是操作系统中一个关键的操作,本实验旨在通过编写一个简单的程序来演示进程的创建过程。
实验目的:通过实验,我们的目标是深入理解进程的创建过程,并了解操作系统是如何管理进程的。
实验步骤:1. 引入必要的头文件:在开始编写代码之前,我们需要引入一些必要的头文件。
这些头文件包括<sys/types.h>、<sys/wait.h>和<unistd.h>。
这些头文件提供了创建进程所需的函数和数据类型。
2. 创建一个子进程:在主程序中,我们使用fork()函数来创建一个子进程。
fork()函数会在当前进程的基础上创建一个新的进程,这个新进程称为子进程。
子进程和父进程几乎完全相同,只有在返回值上有所区别。
如果fork()函数返回0,表示当前进程是子进程;如果返回一个正整数,表示当前进程是父进程。
3. 子进程的执行:在子进程中,我们可以编写任意的代码来执行特定的任务。
子进程可以使用exec()函数来执行其他程序,或者执行一系列的操作。
在本实验中,我们简单地输出一条信息,以展示子进程的执行过程。
4. 父进程的执行:在父进程中,我们可以编写代码来执行其他任务,或者等待子进程的结束。
在本实验中,我们使用wait()函数来等待子进程的结束。
wait()函数会暂停父进程的执行,直到子进程结束为止。
5. 编译和运行程序:在完成代码编写后,我们需要将程序编译成可执行文件,并运行它。
我们可以使用gcc编译器来编译程序,然后运行生成的可执行文件。
实验结果:在运行程序后,我们可以观察到以下结果:子进程开始执行。
父进程等待子进程结束。
子进程结束。
父进程继续执行。
结论:通过本实验,我们成功地演示了进程的创建过程。
我们了解了操作系统是如何管理进程,并且掌握了使用fork()函数来创建子进程的方法。
进程控制实验报告

一、实验目的本次实验旨在通过Linux操作系统的实践操作,加深对进程控制概念的理解。
通过学习进程的创建、调度、同步、通信等基本操作,掌握进程控制的基本方法,并了解进程间通信的机制。
二、实验环境1. 硬件环境:Intel(R) Core(TM) i5-3210M CPU2.50GHz,4.00GB内存。
2. 软件环境:64位Linux操作系统。
三、实验内容1. 进程的创建与终止2. 进程的调度与优先级3. 进程同步与互斥4. 进程间通信四、实验步骤1. 进程的创建与终止(1)使用`fork()`函数创建子进程,通过比较返回值判断创建是否成功。
```cpid_t pid = fork();if (pid < 0) {perror("fork failed");exit(1);}```(2)使用`exit()`函数终止进程。
```cexit(0);```2. 进程的调度与优先级(1)使用`nice()`函数调整进程优先级。
```cnice(10); // 降低进程优先级```(2)使用`priority_seta()`函数设置进程优先级。
```cstruct sched_param param;param.sched_priority = 10;if (sched_setscheduler(pid, SCHED_RR, ¶m) == -1) { perror("sched_setscheduler failed");exit(1);}```3. 进程同步与互斥(1)使用`semaphore_t`类型的信号量实现进程同步。
```csemaphore_t sem;sem_init(&sem, 0, 1);sem_wait(&sem);// 执行临界区代码sem_post(&sem);sem_destroy(&sem);```(2)使用`mutex_t`类型的互斥锁实现进程互斥。
fork系统调用实验原理

fork系统调用实验原理
fork系统调用是UNIX和Linux操作系统中的一个重要功能,它的主要作用是创建一个与原进程几乎完全相同的子进程。
以下是fork系统调用的实验原理:
1. 父进程在调用fork时,会创建一个与父进程几乎完全相同的子进程。
这个子进程会继承父进程的所有内存空间、文件描述符、环境变量等资源。
2. 在子进程创建完成后,fork系统调用会返回两次,一次是在父进程中返回子进程的PID,一次是在子进程中返回0。
这是fork系统调用的一个重要特性,即“一次调用,两次返回”。
3. 在父进程中,fork返回子进程的PID,这样父进程就可以通过这个PID 来对子进程进行控制和通信。
同时,父进程可以继续执行后续的代码,与子进程并行执行。
4. 在子进程中,fork返回0,表示当前是子进程。
子进程可以继续执行后续的代码,与父进程并行执行。
由于子进程是父进程的副本,因此子进程可以独立地运行,不受父进程的影响。
5. fork系统调用的实现原理是基于操作系统的虚拟存储器技术。
在fork过程中,父进程的虚拟存储空间被拷贝给了子进程,这样父子进程就可以共享内存空间。
但是,这种共享只是虚拟存储空间的共享,实际的物理存储器仍然是分开的。
当父子进程对内存进行写操作时,会触发写时拷贝机制,将物
理存储器中的内容复制到新的物理页面中,从而实现多进程的隔离和并发执行。
通过以上原理,我们可以理解到fork系统调用的作用是创建子进程,并实现父子进程的并行执行。
同时,fork系统调用的实现原理是基于虚拟存储器和写时拷贝技术,实现了多进程的隔离和并发执行。
linux进程管理实验心得

linux进程管理实验心得在操作系统课程中,我们进行了一系列关于Linux进程管理的实验。
通过这些实验,我对Linux进程管理有了更深入的理解,并且学到了很多有关进程管理的知识和技巧。
在这篇文章中,我将分享我的实验心得和体会。
首先,我学会了如何创建和终止进程。
在实验中,我们使用了fork()函数来创建子进程,并使用exec()函数来加载新的程序。
这样,我们可以在一个进程中创建多个子进程,并且每个子进程可以执行不同的任务。
而通过调用exit()函数,我们可以终止一个进程的执行。
这些操作让我更加清楚地了解了进程的创建和终止过程。
其次,我学会了如何管理进程的优先级。
在Linux中,每个进程都有一个优先级,用于决定进程在CPU上执行的顺序。
通过使用nice命令,我们可以为进程设置不同的优先级。
较高的优先级意味着进程将更频繁地获得CPU时间片,从而提高了进程的执行效率。
这对于提高系统的整体性能非常重要。
此外,我还学会了如何监控和调试进程。
在实验中,我们使用了ps命令来查看当前系统中正在运行的进程。
通过查看进程的状态和资源使用情况,我们可以了解到系统的运行状况。
而使用top命令,则可以实时地监控进程的运行情况。
此外,我们还学会了使用gdb调试器来调试进程。
通过设置断点和观察变量的值,我们可以找到程序中的错误并进行修复。
最后,我认识到进程管理是操作系统中非常重要的一部分。
一个好的进程管理系统可以提高系统的性能和稳定性。
通过合理地管理进程的创建、终止和调度,可以使系统更加高效地利用资源,并且能够更好地响应用户的需求。
因此,学习和掌握进程管理技术对于成为一名优秀的系统管理员或开发人员来说是非常重要的。
通过这些实验,我不仅学到了很多关于Linux进程管理的知识,还提高了自己的实践能力和问题解决能力。
在实验过程中,我遇到了各种各样的问题,但通过查阅资料、与同学讨论和不断尝试,我最终成功地解决了这些问题。
这让我更加自信地面对未来的挑战。
操作系统实验fork()

并发程序设计【实验目的】:掌握在程序中创建新进程的方法,观察并理解多道程序并发执行的现象。
【实验原理】:fork():建立子进程。
子进程得到父进程地址空间的一个复制。
返回值:成功时,该函数被调用一次,但返回两次,fork()对子进程返回0,对父进程返回子进程标识符(非0值)。
不成功时对父进程返回-1,没有子进程。
【实验内容】:首先分析一下程序运行时其输出结果有哪几种可能性,然后实际调试该程序观察其实际输出情况,比较两者的差异,分析其中的原因。
void main (void){ int x=5;if( fork(()){x+=30;printf (“%d\n”,x);}elseprintf(“%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);}elseprintf("%d\n",x);printf("%d\n",x);}1.2预测结果:(1)553535(2)353555(3)535535(4)535355(5)355355(6)355535(7)35351.3实际结果:administrator@ubuntu:~/yanhong$ cc 1.cadministrator@ubuntu:~/yanhong$ ./a.out353555administrator@ubuntu:~/yanhong$ cc 1.cadministrator@ubuntu:~/yanhong$ ./a.out5535351.4结果分析:结果表明,子进程先执行还是父进程先执行是不确定的。
进程管理实验报告分析(3篇)

第1篇一、实验背景进程管理是操作系统中的一个重要组成部分,它负责管理计算机系统中所有进程的创建、调度、同步、通信和终止等操作。
为了加深对进程管理的理解,我们进行了一系列实验,以下是对实验的分析和总结。
二、实验目的1. 加深对进程概念的理解,明确进程和程序的区别。
2. 进一步认识并发执行的实质。
3. 分析进程争用资源的现象,学习解决进程互斥的方法。
4. 了解Linux系统中进程通信的基本原理。
三、实验内容1. 使用系统调用fork()创建两个子进程,父进程和子进程分别显示不同的字符。
2. 修改程序,使每个进程循环显示一句话。
3. 使用signal()捕捉键盘中断信号,并通过kill()向子进程发送信号,实现进程的终止。
4. 分析利用软中断通信实现进程同步的机理。
四、实验结果与分析1. 实验一:父进程和子进程分别显示不同的字符在实验一中,我们使用fork()创建了一个父进程和两个子进程。
在父进程中,我们打印了字符'a',而在两个子进程中,我们分别打印了字符'b'和字符'c'。
实验结果显示,父进程和子进程的打印顺序是不确定的,这是因为进程的并发执行。
2. 实验二:每个进程循环显示一句话在实验二中,我们修改了程序,使每个进程循环显示一句话。
实验结果显示,父进程和子进程的打印顺序仍然是随机的。
这是因为并发执行的进程可能会同时占用CPU,导致打印顺序的不确定性。
3. 实验三:使用signal()捕捉键盘中断信号,并通过kill()向子进程发送信号在实验三中,我们使用signal()捕捉键盘中断信号(按c键),然后通过kill()向两个子进程发送信号,实现进程的终止。
实验结果显示,当按下c键时,两个子进程被终止,而父进程继续执行。
这表明signal()和kill()在进程控制方面具有重要作用。
4. 实验四:分析利用软中断通信实现进程同步的机理在实验四中,我们分析了利用软中断通信实现进程同步的机理。
进程通讯管理实验报告(3篇)

第1篇一、实验目的1. 理解进程通信的概念和原理;2. 掌握进程通信的常用机制和方法;3. 能够使用进程通信机制实现进程间的数据交换和同步;4. 增强对操作系统进程管理模块的理解。
二、实验环境1. 操作系统:Linux2. 编程语言:C3. 开发环境:GCC三、实验内容1. 进程间通信的管道机制2. 进程间通信的信号量机制3. 进程间通信的共享内存机制4. 进程间通信的消息队列机制四、实验步骤1. 管道机制(1)创建管道:使用pipe()函数创建管道,将管道文件描述符存储在两个变量中,分别用于读和写。
(2)创建进程:使用fork()函数创建子进程,实现父子进程间的通信。
(3)管道读写:在父进程中,使用read()函数读取子进程写入的数据;在子进程中,使用write()函数将数据写入管道。
(4)关闭管道:在管道读写结束后,关闭对应的管道文件描述符。
2. 信号量机制(1)创建信号量:使用sem_open()函数创建信号量,并初始化为1。
(2)获取信号量:使用sem_wait()函数获取信号量,实现进程同步。
(3)释放信号量:使用sem_post()函数释放信号量,实现进程同步。
(4)关闭信号量:使用sem_close()函数关闭信号量。
3. 共享内存机制(1)创建共享内存:使用mmap()函数创建共享内存区域,并初始化数据。
(2)映射共享内存:在父进程和子进程中,使用mmap()函数映射共享内存区域。
(3)读写共享内存:在父进程和子进程中,通过指针访问共享内存区域,实现数据交换。
(4)解除映射:在管道读写结束后,使用munmap()函数解除映射。
4. 消息队列机制(1)创建消息队列:使用msgget()函数创建消息队列,并初始化消息队列属性。
(2)发送消息:使用msgsnd()函数向消息队列发送消息。
(3)接收消息:使用msgrcv()函数从消息队列接收消息。
(4)删除消息队列:使用msgctl()函数删除消息队列。
操作系统实验报告

操作系统实验报告实验项⽬⼆进程管理⼀、实验⽬的1.理解进程的概念,掌握⽗、⼦进程创建的⽅法。
2.认识和了解并发执⾏的实质,掌握进程的并发及同步操作。
⼆、实验内容1.编写⼀C语⾔程序,实现在程序运⾏时通过系统调⽤fork( )创建两个⼦进程,使⽗、⼦三进程并发执⾏,⽗亲进程执⾏时屏幕显⽰“I am father”,⼉⼦进程执⾏时屏幕显⽰“I am son”,⼥⼉进程执⾏时屏幕显⽰“I am daughter”。
2.多次连续反复运⾏这个程序,观察屏幕显⽰结果的顺序,直⾄出现不⼀样的情况为⽌。
记下这种情况,试简单分析其原因。
3.修改程序,在⽗、⼦进程中分别使⽤wait()、exit()等系统调⽤“实现”其同步推进,并获取⼦进程的ID号及结束状态值。
多次反复运⾏改进后的程序,观察并记录运⾏结果。
三、源程序及运⾏结果源程序1:#include#include#includeint 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");}elseprintf("I am father!\n");}sleep(1);return 0;}运⾏结果:源程序2:#include#include#includeint main(int argc, char ** argv ) {char *message;int n;int pid=fork();if(pid < 0)printf("error!");else if( pid == 0 ){message="I am daughter!"; pid=getpid();n=3;}else{int pid=fork();if (pid < 0)printf("error!");else if( pid == 0 ){message="I am son!";pid=getpid();n=3;}elsemessage="I am father!";n=3;}for(;n>0;n--){puts(message);sleep(1);}return 0;}运⾏结果:四、实验分析与总结1.实验内容1运⾏结果为什么⽆固定顺序,fork()函数创建进程是如何并发执⾏的。
进程的管理实验报告

一、实验目的1. 理解进程的基本概念和进程状态转换过程。
2. 掌握进程创建、进程同步和进程通信的方法。
3. 了解进程调度算法的基本原理和实现方法。
4. 通过实验加深对进程管理的理解,提高操作系统实践能力。
二、实验环境1. 操作系统:Linux2. 编程语言:C/C++3. 开发工具:GCC三、实验内容1. 进程创建与状态转换(1)使用fork()函数创建一个子进程,并观察父进程和子进程的进程ID。
(2)使用exec()函数替换子进程的映像,实现进程的创建。
(3)观察进程状态转换过程,如创建、运行、阻塞、就绪、终止等。
2. 进程同步(1)使用互斥锁(mutex)实现进程的互斥访问共享资源。
(2)使用信号量(semaphore)实现进程的同步,如生产者-消费者问题。
(3)观察进程同步的效果,确保进程安全执行。
3. 进程通信(1)使用管道(pipe)实现进程间的单向通信。
(2)使用消息队列(message queue)实现进程间的双向通信。
(3)使用共享内存(shared memory)实现进程间的快速通信。
(4)观察进程通信的效果,确保数据正确传递。
(1)实现基于优先级的进程调度算法,如先来先服务(FCFS)和最高优先级优先(HPF)。
(2)实现基于时间片的轮转调度算法(RR)。
(3)观察进程调度算法的效果,分析不同算法的优缺点。
四、实验步骤1. 编写程序实现进程创建与状态转换,使用fork()和exec()函数。
2. 编写程序实现进程同步,使用互斥锁和信号量。
3. 编写程序实现进程通信,使用管道、消息队列和共享内存。
4. 编写程序实现进程调度,使用优先级调度和时间片轮转调度。
5. 编译并运行程序,观察实验结果,分析实验现象。
五、实验结果与分析1. 进程创建与状态转换通过实验,我们成功创建了父进程和子进程,并观察到进程ID的变化。
在进程创建过程中,父进程的进程ID与子进程的进程ID不同,说明子进程是独立于父进程的实体。
进程创建实验报告

实验二进程的创建一、实验目的熟悉进程的创建过程,了解系统调用函数fork() 和 execl()。
二、实验内容1、阅读实例代码fork1,并编辑、编译、运行,记录程序的运行结果,尝试给出合理的解释,查阅有关资料,掌握系统调用fork( )的用法,返回值的意义。
2、阅读实例代码fork2,并编辑、编译、运行,记录程序的运行结果,尝试给出合理的解释,查阅有关资料,掌握在程序中运行一个操作系统命令和运行一个程序的方法。
3、修改fork2,使之能把运行的命令和程序作为参数传给fork2。
三、设计思想1、程序框架pid = - 1 pid = 0 pid > 02、用到的文件系统调用函数fork() 和 execl()四、调试过程1、测试数据设计(1)fork1命名程序1:编写程序1:编译程序1:(2)fork2编写程序2:(3)修改fork2编写修改程序2:修改后的运行结果:2、测试结果分析(1)对于程序1:因为系统调用fork()函数是一次调用两次返回值,而且先生成子进程还是父进程是不确定的,所以第一次执行生成子进程的时候返回的pid = 0,判断pid!=-1,所以输出了I’m the child. I’m the parent. 第二次,执行父进程的时候,返回的是子进程的进程号pid > 0,即pid的值仍然不为-1,所以又输出了一次I’m the child. I’m the parent。
(2)对于程序2:第一次调用fork()函数时,由于执行的是子进程还是父进程是随机的,所以第一次对父进程返回的是子进程的进程号(大于0),即pid > 0,所以输出I’m the parent. Program end. 当第二次执行子进程时返回值是0,即pid = 0,所以输出I’m the child. 并调用了execl()函数,查看了指定路径中的文件。
(3)对于修改后的程序2:改变了系统调用execl()中参数的文件路径和可执行文件名,即可在程序fork2.c中执行另一个程序wyf.c(但要注意可执行文件名是123)。
父子进程实验报告总结

父子进程实验报告总结1. 引言本实验主要是通过使用父子进程的概念进行实践,深入了解进程的创建和管理的相关知识。
通过实验,我们对进程的创建与退出、进程之间的关系等方面有了更加深入的理解。
2. 实验设计在本次实验中,我们使用C语言编写了一个简单的程序来演示父子进程的创建和管理。
具体的实验设计如下:1. 使用`fork()`函数创建子进程;2. 子进程输出自己的进程ID和父进程的进程ID,然后退出;3. 父进程输出自己的进程ID和子进程的进程ID,并等待子进程退出。
3. 实验过程实验过程如下:1. 首先,我们在代码中使用`fork()`函数创建子进程。
2. 然后,通过判断返回值来确定当前代码是在子进程还是在父进程中,并分别输出相应的进程ID。
3. 子进程打印自己的进程ID以及父进程的进程ID,并立即退出。
4. 父进程打印自己的进程ID以及子进程的进程ID,并使用`wait()`函数等待子进程退出。
5. 最后,父进程输出等待到的子进程的进程ID以及退出状态。
4. 实验结果经过实验,我们得到了以下结果:父进程ID:1234,子进程ID:1235子进程ID:1235,父进程ID:1234实验结果符合我们的预期,说明我们的实验设计是正确的。
5. 实验分析通过本次实验,我们对父子进程有了更加深入的理解。
我们观察到父进程创建了子进程后,子进程会执行完自己的代码后退出,而父进程会继续执行剩余的代码。
这说明父进程和子进程是并发执行的,它们各自有自己的上下文和执行流程。
同时,我们使用了`wait()`函数来等待子进程退出。
这样可以使父进程在子进程退出前一直处于阻塞状态,避免了父进程提前退出导致子进程成为僵尸进程的情况。
6. 实验总结通过本次实验,我们对父子进程的创建和管理有了更加深入的理解。
我们学会了使用`fork()`函数来创建子进程,并理解了父子进程之间的关系。
另外,我们还学会了使用`wait()`函数等待子进程退出,以避免子进程变成僵尸进程。
操作系统实验 fork()

《计算机操作系统》实验报告学号:S030802107 姓名:杨霞学院:数计(软件)学院专业:计算机系年级:2008级班级:1班实验时间:2010-2011学年第一学期并发程序设计(实验1)【实验目的】:掌握在程序中创建新进程的方法,观察并理解多道程序并发执行的现象。
【实验原理】:fork():建立子进程。
子进程得到父进程地址空间的一个复制。
返回值:成功时,该函数被调用一次,但返回两次,fork()对子进程返回0,对父进程返回子进程标识符(非0值)。
不成功时对父进程返回-1,没有子进程。
【实验内容】:首先分析一下程序运行时其输出结果有哪几种可能性,然后实际调试该程序观察其实际输出情况,比较两者的差异,分析其中的原因。
void main (void){ int x=5;if( fork( ) ){x+=30;printf (“%d\n”,x);}elseprintf(“%d\n”,x);printf((“%d\n”,x);}【实验过程】:实验源码:#include<stdio.h>#include<sys/types.h> #include<unistd.h> int main(){int x=5;if(fork()){x+=30;printf("%d\n",x); }elseprintf("%d\n",x); printf("%d\n",x); return 0;}【结果预测】:(1) 5 5 35 35 (2) 35 35 5 5 (7) 35 35 (3)535535(4)535355(5)355355(6)355535【实验结果】:(1) 5 5 35 35 (2) 35 35 5 5预测分析和结果分析:fork()函数是程序创建子进程的调用函数,若子程序创建成功,则对子程序返回0,对父进程返回子程序的ID;若不成功,则返回-1。
fork()函数总结

printf("n=[%d]\n", n++); return 0; }
这个例子在linux下用gcc编译,运行结果如下:
fork! [child]i am child! [child]getpid=[7422] [child]pid=[0] n=[0] [parent]i am parent! [parent]getpid=[7421] [parent]pid=[7422] n=[0]
表,该文件表是由内核维护的,两个进程共享文件状态,偏移量等。这一点很重要,当在父进程中关闭文件时,子进程的文件描述符仍然
有用,相应的文件表也不会被释放。(3)为了提高效率,fork后并不立即复制父进程空间,采用了COW (Copy -On-W rite);当父子进程
任意之一,要修改数据段、堆、栈时,进行复制操作,但仅复制修改区域;)。父子进程间共享的存储空间只有代码段(只读的,且仅共
享fork()后面的代码段)。子进程和父进程继续执行fork调用之后的指令。(4)fork之后,这两个进程执行没有固定的先后顺序,哪个进程先
执行要看系lude <SYS types.h> #include <UNISTD.H> #include <STDIO.H> int main() { pid_t pid; static int n = 0; printf("fork!\n"); switch (pid = fork()) { case -1: { /* ..pid.-1.fork.... */ /* ........ */ /* .......... */ perror("The fork failed!"); break; } case 0: { /* pid.0.... */ printf("[child]i am child!\n"); printf("[child]getpid=[%d]\n", getpid() ); printf("[child]pid=[%d]\n", pid ); break; } default: { /* pid..0.... */ printf("[parent]i am parent!\n" ); printf("[parent]getpid=[%d]\n",getpid() ); printf("[parent]pid=[%d]\n",pid ); break; } }
进程创建撤销实验报告

一、实验目的1. 理解进程的概念及其在操作系统中的作用。
2. 掌握进程创建和撤销的基本原理和方法。
3. 通过实验加深对进程管理机制的理解。
二、实验环境1. 操作系统:Linux2. 编程语言:C/C++3. 编译器:GCC三、实验原理在操作系统中,进程是系统进行资源分配和调度的基本单位。
进程创建是指从无到有地创建一个新的进程,而进程撤销则是指结束一个进程的生命周期。
进程创建和撤销是操作系统进程管理中的重要操作。
四、实验内容1. 进程创建实验2. 进程撤销实验五、实验步骤1. 进程创建实验(1)创建一个新进程```c#include <stdio.h>#include <unistd.h>#include <sys/types.h>int main() {pid_t pid = fork(); // 创建子进程if (pid == -1) {perror("fork failed");return 1;} else if (pid == 0) {// 子进程printf("Child process: PID = %d\n", getpid());// 执行子进程的任务} else {// 父进程printf("Parent process: PID = %d\n", getpid());// 等待子进程结束wait(NULL);}return 0;}```(2)编译并运行程序```bashgcc -o process_create process_create.c./process_create```(3)观察输出结果在控制台会看到两个进程的PID,其中一个为父进程,另一个为子进程。
2. 进程撤销实验(1)创建一个新进程```c#include <stdio.h>#include <unistd.h>#include <sys/types.h>#include <sys/wait.h>int main() {pid_t pid = fork(); // 创建子进程if (pid == -1) {perror("fork failed");return 1;} else if (pid == 0) {// 子进程printf("Child process: PID = %d\n", getpid()); // 执行子进程的任务sleep(10); // 子进程睡眠10秒} else {// 父进程printf("Parent process: PID = %d\n", getpid()); // 等待子进程结束wait(NULL);}return 0;}```(2)编译并运行程序```bashgcc -o process_destroy process_destroy.c./process_destroy```(3)观察输出结果在控制台会看到两个进程的PID,父进程会等待子进程结束。
操作系统实验报告

操作系统实验报告操作系统是计算机科学中十分重要的一门课程,本次实验是关于操作系统的,通过实验,我们可以更深入地了解操作系统的相关知识和操作。
本篇文章将着重介绍本次操作系统实验的内容和实验过程中的收获。
一、实验内容本次实验内容主要涉及操作系统的进程、线程和进程同步三部分。
具体内容包括:1. 进程的创建和管理2. 线程的创建和管理3. 进程同步的实现在实验过程中,我们将分别使用C语言和Linux操作系统实现上述功能。
二、实验过程1. 进程的创建和管理在这一部分实验中,我们要创建多个进程,实现进程的调度和管理功能。
我们采用了Linux系统下的fork()函数,用于创建子进程。
在程序运行时,首先创建一个父进程,然后使用fork()函数创建四个子进程,每个子进程都有自己的进程号(pid),并在屏幕上输出该进程号以示区分。
为了实现进程的调度功能,我们在代码中加入了sleep()函数,用于将进程挂起一段时间,然后再轮流执行其他进程。
2. 线程的创建和管理在这一部分实验中,我们使用了C语言的POSIX线程库pthread.h,实现多线程的功能。
同样地,我们采用了Linux系统下的fork()函数来创建线程。
在代码运行时,我们创建了两个线程,并在屏幕上输出线程号(tid)以示区分。
为了实现线程的调度和管理功能,我们在代码中加入了pthread_join()函数,用于等待线程的执行完成。
3. 进程同步的实现在这一部分实验中,我们使用了Linux系统下的进程同步工具——信号量(semaphore)。
在代码中,我们使用sem_init()函数创建信号量,使用sem_wait()函数阻塞进程或线程,使用sem_post()函数释放进程或线程。
为了更好地理解信号量的工作原理,我们将代码分为生产者和消费者两部分,其中生产者用于向缓冲区添加数据,消费者则用于删除数据。
在这个过程中,我们需要使用信号量控制生产者和消费者的数量,避免出现生产过多或消费过多的情况。
操作系统实验报告二进程管理fork()

if(pid>0){实
验
pid1=fork();内
容
与
具
if(pid1<0){//failed}
elseif (pid1==0){//child2}体
步
骤
else{//parent
}
}
......
#include <sys/types.h>
#include <unistd.h>
闽南师范大学
实验报告
班级学号姓名成绩
同组人实验日期
课程名称:操作系统
实验题目:进程管理1.Fra bibliotek理论课中学习的进程、程序等的概念作进一步的理解,明确进程和程序的区别;
2.加深理解进程并发执行的概念,认识多进程的并发执行的实质;
实
验
目
的
与
要
求
PC兼容机。Window xp以上操作系统
实
验
环
境
的
配
置
第1页
闽南师范大学实验报告
printf("child1 pid is %d\n",getpid());
for(i=0;i<26;i++) {
编写程序,利用fork()产生两个子进程,首先显示两个子进程及父
进程的进程标识符;然后让父进程显示1~26个数字,子进程1显示26
个大写字母,子进程2显示26个小写字母,让大小写字母及数字是夹
杂交错输出的。修改程序,让两个子进程夹杂输出结束后,父进程输出
开始(见图1)
pid=fork();
if(pid<0){//failed}
Linux中的fork函数

Linux中的fork函数操作系统实验⼆fork函数作⽤fork函数将运⾏着的程序分成2个(⼏乎)完全⼀样的进程,每个进程都启动⼀个从代码的同⼀位置开始执⾏的线程返回值负值:创建⼦进程失败。
零:返回到新创建的⼦进程。
正值:返回⽗进程或调⽤者。
该值包含新创建的⼦进程的进程ID⽤法pid_t pid=fork();如果创建成功,会有两个进程:⽗进程和⼦进程,fork在这两个进程中分别返回,就是返回两次且返回值不同。
⼀段程序# include<stdio.h># include<sys/types.h># include<unistd.h>int main(){int pid1, pid2;printf("I am father %d! My father is %d.\n", getpid(), getppid());if ((pid1 = fork())<0) //fork return value < 0 , create failed{printf("Child1 fail create!\n");return 1;}else if (pid1 == 0) //fork return value = 0, son is running{printf("I am son %d! My father is %d. \n", getpid(), getppid());return 0;}if ((pid2 = fork())<0){printf("Child2 fail create!\n");return 0;}else if (pid2 == 0){printf("I am daughter %d! My father is %d.\n", getpid(), getppid());return 0;}}编译运⾏gcc fork.c -o fork./fork运⾏结果分析:⾸先是⽗进程,打印了它的⾝份和进程号,还有它的⽗进程号在第⼀个if语句中创建了⼦进程,⼦进程创建成功,返回值是0,执⾏第⼀个else if,打印⾝份是⼦进程和它的进程号和⽗进程号。
武汉大学操作系统大作业 - 2

武汉大学操作系统大作业 - 2Fork、Pthread实验报告一、学习目标1.学习fork函数和pthread函数的使用,阅读源码,分析两个函数的机理。
2.在系统中创建一个三层次父子进程树,并具有两层次线程,并打印运行中各个执行体的处理器使用、内存使用等基本信息。
二、基本原理1、fork函数fork函数的函数原型是pid_t fork( void)。
fork()函数的响应函数是 sys_fork()、sys_clone()、sys_vfork()。
这三个函数都是通过调用内核函数 do_fork() 来实现的。
使用do_fork()函数创建一个进程大致分为如下几个过程:(1)向系统申请在内存中分配一个 task_struct 数据结构,即进程控制块PCB,do_fork()中通过使用alloc_task_struct()实现。
task_struct是LINUX内核用以管理进程的结构体,它包含了进程状态、PID、内核栈等等执行进程所必须要的资源。
(2)对PCB进行初始化操作。
通过执行*p=*curren,将父进程(当前进程)的PCB内容拷贝到新进程中去,重新设置 task_struct 结构中那些与父进程值不同的数据成员,为进程分配标志号。
根据参数中传入的 clone_flags 参数值,决定是否要拷贝父进程task_struct 中的指针 fs 、files 指针等所选择的部分。
(3)将新进程加入到进程链表中去,并拷贝父进程的上下文来初始化子进程上下文。
启动调度程序,通过wake_up_process(p)唤醒子进程,并放入就绪队列当中。
父进程返回子进程的PID,子进程返回0。
通过do_fork()函数以及示例代码运行结果,可以了解到fork()函数的如下特点:(1)fork函数返回值Pid_t 是在头文件sys/types.h中定义的宏,在调用fork后会返回两个值,如果是子进程则返回值为0,如果是父进程则返回值大于0(为子进程的PID),如果创建进程失败则返回值小于0。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
针对fork函数难以理解,根据网上的解释,参考他人代码,做了如下实验,并附以实验分析
2 #include <sys/types.h>
3 #include <sys/wait.h>
4 #include <unistd.h>
5 #include <stdio.h>
6 #include <stdlib.h>
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)
小结:这段代码总共有4个进程,pid分别为
13199--main这个父进程自身的pid
13200--main这个父进程建立的pc进程pid=13200
13201--pc这个子进程创建的子进程,即main的孙进程pr
13254--main这个父进程创建的子进程pr 此处的pr与上一处pc创建的不同,从其pid上可做区别。
这说明fork的工作原理:
1.pc=fork()函数创建自身时复制了如下代码段
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 }
2.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 }
用图表示其关系为。