武汉大学操作系统大作业

发布 2020-02-28 15:16:28 阅读 5789

fork、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/中定义的宏,在调用fork后会返回两个值,如果是子进程则返回值为0,如果是父进程则返回值大于0(为子进程的pid),如果创建进程失败则返回值小于0。

2)通过fork函数创建的新进程是对父进程的复制,子进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致。通过示例**1.1可以看见父、子进程最后执行结果中count的值都是1,这是因为子进程拷贝的是父进程当前的状态, count为0,执行了‘++操作变为1。

3)父进程和子进程的概念是相对的,如运行结果1.2所示,p722是p719的子进程,也是p724的父进程。父进程和子进程的执行顺序是不一定的,这依赖于系统调度。

子进程和父进程的可执行程序是同一个程序、上下文和数据,绝大部分就是原进程(父进程)的拷贝,但它们是两个相互独立的进程,fork()以后,子进程就相当于父进程的兄弟一样了。

4)在运行结果1.1中可以看见子进程输出时父进程的id为1,这是因为在子进程执行printf语句的时候,父进程已经结束了,对于没有父进程的子进程系统会将其父进程置为init(pid为1)进程。

**示例1.1

运行结果1.1

示例**1.2

运行结果1.2

注】 **示例1.1运行结果如运行结果1.1所示,示例**1.2运行结果如运行结果1.2所示。

2、pthread函数。

pthread中定义了一系列线程操作函数、同步互斥函数,此次主要学习了pthread_create()、pthread_join()、pthread_exit()函数。

1)pthread_create()函数用于线程创建,第一个参数pthread_t *thread用于存储创建成功的线程的id。第二个参数const pthread_attr_t * attr 用于给定线程属性,置为null则使用默认属性。

pthread_create()源**中,新进程的参数、信息均被打包到request结构中,再通过__libc_write(__pthread_manager_request, (char *)request, sizeof(request)),将请求写入全局变量__pthread_manager_request,最后由__pthread_manager()函数创建并管理线程。

(2)pthread_join()函数用于挂起线程,第一个参数pthread_t thread,用于指定次需要等待结束的线程,当thread指定的线程没有终止,将导致调用线程挂起,直到由参数thread指定的线程终止。最后一个参数void**status是通过pthread_exit()函数传递进来的,如作业**中主线程要等待线程1结束,而线程1要等待线程2结束。

(3)pthread_exit()函数用于结束线程,参数status将子线程的结束状态传递给主线程。主线程可以在pthread_join()成功返回后获得子线程的结束状态,并根据不同的结束状态做不同的处理。

通过运行示例**可以发现线程的一些特点:

(1)子线程的创建顺序与子线程执行顺序是不一致,子线程的执行顺序是随机的,依赖于操作系统的调度。如运行结果2.1.1和2.1.2所示,两个子线程执行顺序是随机的。

2)示例**2.1中,线程1线程2对number都有写操作,所以在修改number值的时候要进行加锁和解锁的操作,避免出现结果不唯一结果。如果去掉互斥锁,可以看见如运行结果2.

1.2所示number值出现了错误。

3)线程没有独立的存储空间,同一进程下的线程共享存储空间,所以在运行结果2.1.1中我们看到number的结果是逐渐累加的,在作业**运行结果中也可以看到线程与创建他们的进程共用一个内存地址,且pid均为父进程的pid。

其实,线程有各自的线程id,可以通过pthread_self()获得。

示例**2.1两个子线程。

运行结果2.1.1

运行结果2.1.2

【注】 **示例2.1运行结果如运行结果2.1.1和2.1.2所示。

三、实验结果。

1、**及运行结果截图。

作业** 3.1.1 第一次fork

作业** 3.1.2 第二次fork

作业** 3.1.3 子线程定义。

运行结果3.1

2、心得体会。

通过此次学习,我对进程、线程的概念有了进一步的认识,初步了解了fork、pthread的原理以及使用方法,但是此次实验仍有不足的地方。

(1)相关知识不足,在看fork和pthread源**的时候有很多不明白的地方,尤其是pthread部分。

2)对部分**的运行结果不能很好的理解。

3)**中没有实现打印处理器使用、内存使用等基本信息。

四、附件。/源**。

/ created by yi mingli on 16/4/1.

/ copyright (c) 2023年 yi mingli. all rights reserved.

#include <>

#include <>

#include <>

#include

#include <>

#define thread_num 2

pthread_t threads[thread_num线程返回数组。

pthread_mutex_t mut;

int number=0;

void *thread2()

printf("i am thread2,my pid is %d,and my id is %lu (0x%x)",getpid(),pthread_self(),getpid())

pthread_exit(null);

return null;

void *thread1()

printf("i am thread1,my pid is %d,and my id is %lu (0x%x)",getpid(),pthread_self(),getpid())

int sthread=pthread_create(&threads[1], null, (void*)thread2, null创建线程2

if (sthread)

if (threads[1]!=0)

pthread_exit(null);

return null;

int main(int argc, const char * ar**)

pid_t fpid=fork创建第一个子进程。

if (fpid<0)

printf("error in fork 1!");

进程创建失败。

else if (fpid==0子进程。

printf("i am process2,my father process is %d,my id is %d,and the value of fpid is %d (0x%x)",getppid(),getpid(),fpid,getpid())

pid_t sfpid=fork创建第二个进程。

if (sfpid<0)

printf("error in fork 2!");

else if(sfpid==0)

printf("i am process3,my father process is %d,my id is %d,and the value of fpid is %d (0x%x)",getppid(),getpid(),sfpid,getpid())

操作系统大作业a

一 填空 14分 1 在设备管理中,为了克服独占设备速度较慢 降低设备资源利用率的缺点,引入了虚拟分配技术即用共享设备模拟独占设备。2 常用的内存管理方法有和。3 动态存储分配时,要靠硬件地址变换机构实现重定位。4 在存储管理中常用虚拟存储器方式来摆脱主存容量的限制。5 在页式管理中,页式虚地址与内...

操作系统大作业a

一 填空 14分 1 在设备管理中,为了克服独占设备速度较慢 降低设备资源利用率的缺点,引入了即用共享设备模拟独占设备。2 常用的内存管理方法有和。3 动态存储分配时,要靠硬件地址变换机构实现。4 在存储管理中常用方式来摆脱主存容量的限制。5 在页式管理中,页式虚地址与内存物理地址的映射是由和完成的...

操作系统大作业

学号 091401223 姓名 高玉林 本次上机作业使用的软件是microsoft visual studio community 2017 rc,版本 15.0.26020.0,使用的语言是c 第一题 编写求f x 值的程序。f x f1 x f2 x f3 x f1 x 10 x f2 x 10...