实验一一进程的创建实验Word下载.docx

上传人:b****4 文档编号:7991543 上传时间:2023-05-09 格式:DOCX 页数:22 大小:32.12KB
下载 相关 举报
实验一一进程的创建实验Word下载.docx_第1页
第1页 / 共22页
实验一一进程的创建实验Word下载.docx_第2页
第2页 / 共22页
实验一一进程的创建实验Word下载.docx_第3页
第3页 / 共22页
实验一一进程的创建实验Word下载.docx_第4页
第4页 / 共22页
实验一一进程的创建实验Word下载.docx_第5页
第5页 / 共22页
实验一一进程的创建实验Word下载.docx_第6页
第6页 / 共22页
实验一一进程的创建实验Word下载.docx_第7页
第7页 / 共22页
实验一一进程的创建实验Word下载.docx_第8页
第8页 / 共22页
实验一一进程的创建实验Word下载.docx_第9页
第9页 / 共22页
实验一一进程的创建实验Word下载.docx_第10页
第10页 / 共22页
实验一一进程的创建实验Word下载.docx_第11页
第11页 / 共22页
实验一一进程的创建实验Word下载.docx_第12页
第12页 / 共22页
实验一一进程的创建实验Word下载.docx_第13页
第13页 / 共22页
实验一一进程的创建实验Word下载.docx_第14页
第14页 / 共22页
实验一一进程的创建实验Word下载.docx_第15页
第15页 / 共22页
实验一一进程的创建实验Word下载.docx_第16页
第16页 / 共22页
实验一一进程的创建实验Word下载.docx_第17页
第17页 / 共22页
实验一一进程的创建实验Word下载.docx_第18页
第18页 / 共22页
实验一一进程的创建实验Word下载.docx_第19页
第19页 / 共22页
实验一一进程的创建实验Word下载.docx_第20页
第20页 / 共22页
亲,该文档总共22页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

实验一一进程的创建实验Word下载.docx

《实验一一进程的创建实验Word下载.docx》由会员分享,可在线阅读,更多相关《实验一一进程的创建实验Word下载.docx(22页珍藏版)》请在冰点文库上搜索。

实验一一进程的创建实验Word下载.docx

这些区是可被共享和保护的独立实体,多个进程可共享一个区。

为了对区进行管理,核心中设置一个系统区表,各表项中记录了以下有关描述活动区的信息:

区的类型和大小、区的状态、区在物理存储器中的位置、引用计数、指向文件索引结点的指针。

4、进程区表

系统为每个进程配置了一张进程区表。

表中,每一项记录一个区的起始虚地址及指向系统区表中对应的区表项。

核心通过查找进程区表和系统区表,便可将区的逻辑地址变换为物理地址。

二、进程映像

UNIX系统中,进程是进程映像的执行过程,也就是正在执行的进程实体。

它由三部分组成:

1、用户级上、下文。

主要成分是用户程序;

2、寄存器上、下文。

由CPU中的一些寄存器的内容组成,如PC,PSW,SP及通用寄存器等;

3、系统级上、下文。

包括OS为管理进程所用的信息,有静态和动态之分。

三、所涉及的系统调用

1、fork()

创建一个新进程。

系统调用格式:

pid=fork()

参数定义:

intfork()

fork()返回值意义如下:

0:

在子进程中,pid变量保存的fork()返回值为0,表示当前进程是子进程。

>

在父进程中,pid变量保存的fork()返回值为子进程的id值(进程唯一标识符)。

-1:

创建失败。

如果fork()调用成功,它向父进程返回子进程的PID,并向子进程返回0,即fork()被调用了一次,但返回了两次。

此时OS在内存中建立一个新进程,所建的新进程是调用fork()父进程(parentprocess)的副本,称为子进程(childprocess)。

子进程继承了父进程的许多特性,并具有与父进程完全相同的用户级上下文。

父进程与子进程并发执行。

核心为fork()完成以下操作:

(1)为新进程分配一进程表项和进程标识符

进入fork()后,核心检查系统是否有足够的资源来建立一个新进程。

若资源不足,则fork()系统调用失败;

否则,核心为新进程分配一进程表项和唯一的进程标识符。

(2)检查同时运行的进程数目

超过预先规定的最大数目时,fork()系统调用失败。

(3)拷贝进程表项中的数据

将父进程的当前目录和所有已打开的数据拷贝到子进程表项中,并置进程的状态为“创建”状态。

(4)子进程继承父进程的所有文件

对父进程当前目录和所有已打开的文件表项中的引用计数加1。

(5)为子进程创建进程上、下文

进程创建结束,设子进程状态为“内存中就绪”并返回子进程的标识符。

(6)子进程执行

虽然父进程与子进程程序完全相同,但每个进程都有自己的程序计数器PC(注意子进程的PC开始位置),然后根据pid变量保存的fork()返回值的不同,执行了不同的分支语句。

例:

…..

pid=fork();

if(!

pid)

printf("

I'

mthechildprocess!

\n"

);

elseif(pid>

0)

mtheparentprocess!

\n"

else

Forkfail!

……

PC

fork()调用前

fork()调用后

\n"

 

实验二进程管理

进程互斥实验

1、进一步认识并发执行的实质

2、分析进程竞争资源的现象,学习解决进程互斥的方法

1、修改实验

(一)中的程序,用lockf()来给每一个进程加锁,以实现进程之间的互斥

2、观察并分析出现的现象

一、所涉及的系统调用

lockf(files,function,size)

用作锁定文件的某些段或者整个文件。

本函数的头文件为

#include"

unistd.h"

intlockf(files,function,size)

intfiles,function;

longsize;

其中:

files是文件描述符;

function是锁定和解锁:

1表示锁定,0表示解锁。

size是锁定或解锁的字节数,为0,表示从文件的当前位置到文件尾。

三、运行结果

四、分析原因

上述程序执行时,不同进程之间不存在共享临界资源(其中打印机的互斥性已由操作系统保证)问题,所以加锁与不加锁效果相同。

五、分析以下程序的输出结果:

#include<

stdio.h>

unistd.h>

main()

{

intp1,p2,i;

int*fp;

fp=fopen("

to_be_"

"

w+"

if(fp==NULL)

{

Failtocreatefile"

exit(-1);

}

while((p1=fork())==-1);

/*创建子进程p1*/

if(p1==0)

lockf(*fp,1,0);

/*加锁*/

for(i=0;

i<

10;

i++)

fprintf(fp,"

daughter%d\n"

i);

lockf(*fp,0,0);

/*解锁*/

}

else

while((p2=fork())==-1);

/*创建子进程p2*/

if(p2==0)

fprintf(fp,"

son%d\n"

lockf(*fp,0,0);

wait(NULL);

lockf(*fp,1,0);

for(i=0;

parent%d\n"

fclose(fp);

catto_be_查看输出结果

实验二进程间通信

UNIX/LINUX系统的进程间通信机构(IPC)允许在任意进程间大批量地交换数据。

本实验的目的是了解和熟悉LINUX支持的信号量机制、管道机制、消息通信机制及共享存储区机制。

(一)信号机制实验

1、了解什么是信号

2、熟悉LINUX系统中进程之间软中断通信的基本原理

1、编写程序:

用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上来的中断信号(即按^c键);

捕捉到中断信号后,父进程用系统调用kill()向两个子进程发出信号,子进程捕捉到信号后分别输出下列信息后终止:

Childprocess1iskilledbyparent!

Childprocess2iskilledbyparent!

父进程等待两个子进程终止后,输出如下的信息后终止:

Parentprocessiskilled!

2、分析利用软中断通信实现进程同步的机理

一、信号

1、信号的基本概念

每个信号都对应一个正整数常量(称为signalnumber,即信号编号。

定义在系统头文件<

signal.h>

中),代表同一用户的诸进程之间传送事先约定的信息的类型,用于通知某进程发生了某异常事件。

每个进程在运行时,都要通过信号机制来检查是否有信号到达。

若有,便中断正在执行的程序,转向与该信号相对应的处理程序,以完成对该事件的处理;

处理结束后再返回到原来的断点继续执行。

实质上,信号机制是对中断机制的一种模拟,故在早期的UNIX版本中又把它称为软中断。

信号与中断的相似点:

(1)采用了相同的异步通信方式;

(2)当检测出有信号或中断请求时,都暂停正在执行的程序而转去执行相应的处理程序;

(3)都在处理完毕后返回到原来的断点;

(4)对信号或中断都可进行屏蔽。

信号与中断的区别:

(1)中断有优先级,而信号没有优先级,所有的信号都是平等的;

(2)信号处理程序是在用户态下运行的,而中断处理程序是在核心态下运行;

(3)中断响应是及时的,而信号响应通常都有较大的时间延迟。

信号机制具有以下三方面的功能:

(1)发送信号。

发送信号的程序用系统调用kill()实现;

(2)预置对信号的处理方式。

接收信号的程序用signal()来实现对处理方式的预置;

(3)收受信号的进程按事先的规定完成对相应事件的处理。

2、信号的发送

信号的发送,是指由发送进程把信号送到指定进程的信号域的某一位上。

如果目标进程正在一个可被中断的优先级上睡眠,核心便将它唤醒,发送进程就此结束。

一个进程可能在其信号域中有多个位被置位,代表有多种类型的信号到达,但对于一类信号,进程却只能记住其中的某一个。

进程用kill()向一个进程或一组进程发送一个信号。

3、对信号的处理

当一个进程要进入或退出一个低优先级睡眠状态时,或一个进程即将从核心态返回用户态时,核心都要检查该进程是否已收到软中断。

当进程处于核心态时,即使收到软中断也不予理睬;

只有当它返回到用户态后,才处理软中断信号。

对软中断信号的处理分三种情况进行:

(1)如果进程收到的软中断是一个已决定要忽略的信号(function=1),进程不做任何处理便立即返回;

(2)进程收到软中断后便退出(function=0);

(3)执行用户设置的软中断处理程序。

二、所涉及的中断调用

1、kill()

系统调用格式

intkill(pid,sig)

参数定义

intpid,sig;

其中,pid是一个或一组进程的标识符,参数sig是要发送的软中断信号。

(1)pid>

0时,核心将信号发送给进程pid。

(2)pid=0时,核心将信号发送给与发送进程同组的所有进程。

(3)pid=-1时,核心将信号发送给所有用户标识符真正等于发送进程的有效用户标识号的进程。

2、signal()

预置对信号的处理方式,允许调用进程控制软中断信号。

signal(sig,function)

头文件为

 #include<

intsig;

void(*func)()

其中sig用于指定信号的类型,sig为0则表示没有收到任何信号,余者如下表:

名字

说明

01

SIGHUP

挂起(hangup)

02

SIGINT

中断,当用户从键盘按^c键或^break键时

03

SIGQUIT

退出,当用户从键盘按quit键时

04

SIGILL

非法指令

05

SIGTRAP

跟踪陷阱(tracetrap),启动进程,跟踪代码的执行

06

SIGIOT

IOT指令

07

SIGEMT

EMT指令

08

SIGFPE

浮点运算溢出

09

SIGKILL

杀死、终止进程

10

SIGBUS

总线错误

11

SIGSEGV

段违例(segmentationviolation),进程试图去访问其虚地址空间以外的位置

12

SIGSYS

系统调用中参数错,如系统调用号非法

13

SIGPIPE

向某个非读管道中写入数据

14

SIGALRM

闹钟。

当某进程希望在某时间后接收信号时发此信号

15

SIGTERM

软件终止(softwaretermination)

16

SIGUSR1

用户自定义信号1

17

SIGUSR2

用户自定义信号2

18

SIGCLD

某个子进程死

19

SIGPWR

电源故障

function:

在该进程中的一个函数地址,在核心返回用户态时,它以软中断信号的序号作为参数调用该函数,对除了信号SIGKILL,SIGTRAP和SIGPWR以外的信号,核心自动地重新设置软中断信号处理程序的值为SIG_DFL,一个进程不能捕获SIGKILL信号。

function的解释如下:

(1)function=1时,进程对sig类信号不予理睬,亦即屏蔽了该类信号;

(2)function=0时,缺省值,进程在收到sig信号后应终止自己;

(3)function为非0,非1类整数时,function的值即作为信号处理程序的指针。

四、运行结果

五、分析原因

六、思考

1、该程序段前面部分用了两个wait(0),它们起什么作用?

2、该程序段中每个进程退出时都用了语句exit(0),为什么?

3、为何预期的结果并未显示出?

4、程序该如何修改才能得到正确结果?

5、不修改程序如何得到期望的输出?

实验三进程通信

(二)进程的管道通信实验

1、了解什么是管道

2、熟悉UNIX/LINUX支持的管道通信方式

编写程序实现进程的管道通信。

用系统调用pipe()建立一管道,二个子进程P1和P2分别向管道各写一句话:

Child1issendingamessage!

Child2issendingamessage!

父进程从管道中读出二个来自子进程的信息并显示(要求先接收P1,后P2)。

一、什么是管道

UNIX系统在OS的发展上,最重要的贡献之一便是该系统首创了管道(pipe)。

这也是UNIX系统的一大特色。

所谓管道,是指能够连接一个写进程和一个读进程的、并允许它们以生产者—消费者方式进行通信的一个共享文件,又称为pipe文件。

由写进程从管道的写入端(句柄1)将数据写入管道,而读进程则从管道的读出端(句柄0)读出数据。

句柄fd[0]

句柄fd[1]

读出端

写入端

二、管道的类型:

1、有名管道

一个可以在文件系统中长期存在的、具有路径名的文件。

用系统调用mknod()建立。

它克服无名管道使用上的局限性,可让更多的进程也能利用管道进行通信。

因而其它进程可以知道它的存在,并能利用路径名来访问该文件。

对有名管道的访问方式与访问其他文件一样,需先用open()打开。

2、无名管道

一个临时文件。

利用pipe()建立起来的无名文件(无路径名)。

只用该系统调用所返回的文件描述符来标识该文件,故只有调用pipe()的进程及其子孙进程才能识别此文件描述符,才能利用该文件(管道)进行通信。

当这些进程不再使用此管道时,核心收回其索引结点。

二种管道的读写方式是相同的,本文只讲无名管道。

3、pipe文件的建立

分配磁盘和内存索引结点、为读进程分配文件表项、为写进程分配文件表项、分配用户文件描述符

4、读/写进程互斥

内核为地址设置一个读指针和一个写指针,按先进先出顺序读、写。

为使读、写进程互斥地访问pipe文件,需使各进程互斥地访问pipe文件索引结点中的直接地址项。

因此,每次进程在访问pipe文件前,都需检查该索引文件是否已被上锁。

若是,进程便睡眠等待,否则,将其上锁,进行读/写。

操作结束后解锁,并唤醒因该索引结点上锁而睡眠的进程。

三、所涉及的系统调用

1、pipe()

建立一无名管道。

pipe(filedes)

intpipe(filedes);

intfiledes[2];

其中,filedes[1]是写入端,filedes[0]是读出端。

该函数使用头文件如下:

#include<

#inlcude<

2、read()

系统调用格式

read(fd,buf,nbyte)

功能:

从fd所指示的文件中读出nbyte个字节的数据,并将它们送至由指针buf所指示的缓冲区中。

如该文件被加锁,等待,直到锁打开为止。

参数定义

intread(fd,buf,nbyte);

intfd;

char*buf;

unsignednbyte;

3、write()

功能:

把nbyte个字节的数据,从buf所指向的缓冲区写到由fd所指向的文件中。

如文件加锁,暂停写入,直至开锁。

参数定义同read()。

五、运行结果

六、思考题

1、程序中的sleep(5)起什么作用?

2、子进程1和2为什么也能对管道进行操作?

(三)消息的发送与接收实验

1、了解什么是消息

2、熟悉消息传送的机理

消息的创建、发送和接收。

使用系统调用msgget(),msgsnd(),msgrev(),及msgctl()编制一长度为1k的消息发送和接收的程序。

一、什么是消息

消息(message)是一个格式化的可变长的信息单元。

消息机制允许由一个进程给其它任意的进程发送一个消息。

当一个进程收到多个消息时,可将它们排成一个消息队列。

消息使用二种重要的数据结构:

一是消息首部,其中记录了一些与消息有关的信息,如消息数据的字节数;

二个消息队列头表,其每一表项是作为一个消息队列的消息头,记录了消息队列的有关信息。

1、消息机制的数据结构

(1)消息首部

记录一些与消息有关的信息,如消息的类型、大小、指向消息数据区的指针、消息队列的链接指针等。

(2)消息队列头表

其每一项作为一个消息队列的消息头,记录了消息队列的有关信息如指向消息队列中第一个消息和指向最后一个消息的指针、队列中消息的数目、队列中消息数据的总字节数、队列所允许消息数据的最大字节总数,还有最近一次执行发送操作的进程标识符和时间、最近一次执行接收操作的进程标识符和时间等。

2、消息队列的描述符

UNIX中,每一个消息队列都有一个称为关键字(key)的名字,是由用户指定的;

消息队列有一消息队列描述符,其作用与用户文件描述符一样,也是为了方便用户和系统对消息队列的访问。

二、涉及的系统调用

1.msgget()

创建一个消息,获得一个消息的描述符。

核心将搜索消息队列头表,确定是否有指定名字的消息队列。

若无,核心将分配一新的消息队列头,并对它进行初始化,然后给用户返回一个消息队列描述符,否则它只是检查消息队列的许可权便返回。

msgqid=msgget(key,flag)

sys/types.h>

sys/ipc.h>

sys/msg.h>

intmsgget(key,flag)

key_tkey;

intflag;

key是用户指定的消息队列的名字;

flag是用户设置的标志和访问方式。

如IPC_CREAT|0400是否该队列已被创建。

无则创建,是则打开;

IPC_EXCL|0400是否该队列的创建应是互斥的。

msgqid是该系统调用返回的描述符,失败则返回-1。

2.msgsnd()

发送一消息。

向指定的消息队列发送一个消息,并将该消息链接到该消息队列的尾部。

msgsnd(msgqid,msgp,size,flag)

intmsgsnd(msgqid,msgp,size,flag)

Iintmsgqid,size,flag;

structmsgbuf*msgp;

其中msgqid是返回消息队列的描述符;

msgp是指向用户消息缓冲区的一个结构体指针。

缓冲区中包括消息类型和消息正文,即

longmtype;

/*消息类型*/

charmtext[];

/*消息的文本*/

size指示由msgp指向的数据结构中字符数组的长度;

即消息的长度。

这个数组的最大值由MSG-MAX()系统可调用参数来确定。

flag规定当核心用尽内部缓冲空间时应执行的动作:

进程是等待,还是立即返回。

若在标志flag中未设置IPC_NOWAIT位,则当该消息队列中的字节数超过最大值时,或系统范围的消息数超过某一最大值时,调用msgsnd进程睡眠。

若是设置IPC_NOWAIT,则在此情况下,msgsnd立即返回。

对于msgsnd(),核心须完成以下工作:

(1)对消息队列的描述符和许可权及消息长度等进行检查。

若合法才继续执行,否则返回;

(2)核心为消息分配消息数据区。

将用户消息

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 自然科学 > 物理

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2