操作系统实验4.docx

上传人:b****6 文档编号:13777055 上传时间:2023-06-17 格式:DOCX 页数:17 大小:189.89KB
下载 相关 举报
操作系统实验4.docx_第1页
第1页 / 共17页
操作系统实验4.docx_第2页
第2页 / 共17页
操作系统实验4.docx_第3页
第3页 / 共17页
操作系统实验4.docx_第4页
第4页 / 共17页
操作系统实验4.docx_第5页
第5页 / 共17页
操作系统实验4.docx_第6页
第6页 / 共17页
操作系统实验4.docx_第7页
第7页 / 共17页
操作系统实验4.docx_第8页
第8页 / 共17页
操作系统实验4.docx_第9页
第9页 / 共17页
操作系统实验4.docx_第10页
第10页 / 共17页
操作系统实验4.docx_第11页
第11页 / 共17页
操作系统实验4.docx_第12页
第12页 / 共17页
操作系统实验4.docx_第13页
第13页 / 共17页
操作系统实验4.docx_第14页
第14页 / 共17页
操作系统实验4.docx_第15页
第15页 / 共17页
操作系统实验4.docx_第16页
第16页 / 共17页
操作系统实验4.docx_第17页
第17页 / 共17页
亲,该文档总共17页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

操作系统实验4.docx

《操作系统实验4.docx》由会员分享,可在线阅读,更多相关《操作系统实验4.docx(17页珍藏版)》请在冰点文库上搜索。

操作系统实验4.docx

操作系统实验4

实验四进程治理--进程的互斥及信号通信

一.目的和要求

(1)进一步熟悉进程并发执行的实质,明白得进程的同步、互斥、撤消等操纵方式;

(2)熟悉进程间通过软中断信号传递操纵信息的方式(低级通信)

二.实验内容

一、编写一段程序,实现软中断通信:

利用系统挪用fork()创建两个子进程,父进程用系统挪用kill()向两个子进程别离发送整数值为SIGUSR1和SIGUSR2软中断信号,子进程取得对应软中断信号后,别离输出以下信息后终止:

Childprocess1iskilledbyparent!

!

Childprocess2iskilledbyparent!

!

父进程挪用wait()函数等待两个子进程终止后,输出以下信息后终止:

Parentprocessiskilled!

!

多运行几回编写的程序,简略分析显现不同结果的缘故。

二、编写一段程序,实现进程互斥。

运行下面的程序,观看程序的执行结果:

#include<>

main()

{inti,p1,p2;

while((p1=fork())==-1);/*父进程创建第一个子进程,直到成功*/

if(p1==0)/*0返回给子进程p1*/

for(i=0;i<5;i++)/*p1的处置进程*/

printf(“Child1%d\n”,i);

else{/*正数返回给父进程(即子进程号)*/

while((p2=fork())==-1);/*父进程创建第二个子进程,直到成功*/

if(p2==0)/*0返回给子进程p2*/

for(i=0;i<5;i++)/*p2的处置进程*/

printf(“Child2%d\n”,i);

else

for(i=0;i<5;i++)/*p2创建完成后,父进程的处置进程*/

printf(“Parent%d\n”,i);

}

}

多次运行程序,观看运行结果。

将上述代码中的三处for(i=0;i<5;i++)改成for(i=0;i<1000;i++),分析执行结果的转变。

由于进程没有同步方法,因此父进程与子进程的输出内容会叠加在一路,输出顺序带有随机性。

多次运行,取得其中一次结果的部份截屏为:

此刻,要求每一个进程一次性输出多项信息到文件,即不许诺多个进程的信息交叉输出,这涉及进程的互斥。

为了实现多个进程对临界资源互斥地正确访问,必需在进入临界区之前执行一个进入区,在临界区以后执行一个退出区。

此刻文件是临界资源,不同进程共享那个临界资源。

对文件的互斥访问,必需在对文件进行存取之前执行一个进入区(加锁),在对文件进行存取以后执行一个退出区(解锁)。

能够利用系统挪用lockf实现不同进程对文件的互斥存取。

进程互斥流程图:

三.实验提示

相关的系统挪用:

一、wait()

等待子进程运行终止。

若是子进程没有完成,父进程一直等待。

wait()将挪用进程挂起,直至其子进程因暂停或终止而发来软中断信号将其唤醒为止。

若是在wait()前已有子进程暂停或终止,那么挪用进程做适当处置后便返回。

系统挪用格式:

int wait(status) 

int *status;

其中,status是用户空间的地址。

它的低8位反映子进程状态,为0表示子进程正常终止,非0那么表示显现了各类各样的问题;高8位那么带回了exit()的返回值。

exit()返回值由系统给出。

二、exit()

终止本进程的执行。

本系统挪用的头文件为:

#include""

系统挪用格式:

voidexit(status)

  intstatus;

其中,status是返回给父进程的一个整数,以备查考。

为了及时回收进程所占用的资源并减少父进程的干与,UNIX/LINUX利用exit()来实现进程的自我终止,通常父进程在创建子进程时,应在进程的末尾安排一条exit(),使子进程自我终止。

exit(0)表示进程正常终止,exit

(1)表示进程运行有错,异样终止。

若是挪用进程在执行exit()时,其父进程正在等待它的终止,那么父进程可当即取得其返回的整数。

3、lockf()

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

本系统挪用的头文件为:

#include""

系统挪用格式:

int lockf(files,function,size)

int files,function;

long size;

其中:

files是文件描述符;function是锁定和解锁:

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

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

4、kill( )

向一个或一组进程发送一个软中断信号。

软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。

进程之间能够相互通过系统挪用kill()发送软中断信号。

内核也能够因为内部事件而给进程发送信号,通知进程发生了某个事件。

注意,信号只是用来通知某进程发生了什么事件,并非给该进程传递任何数据。

系统挪用格式:

int kill(pid,sig)

int pid,sig;

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

(1)pid>0时,核心将信号发送给进程pid。

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

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

在命令提示符下利用kill–l能够查看有哪些信号。

关于这些信号的详细说明请查看命令man7signal的输出结果。

信号事件的发生有两个来源:

一个是硬件的缘故(比如按下了某个键),一个是软件的缘故(比如利用系统函数或命令发出信号)。

五、signal()

预置对信号的处置方式,许诺挪用进程操纵软中断信号。

收到信号的进程对各类信号有不同的处置方式。

处置方式能够分为三类:

第一种是类似中断的处置程序,关于需要处置的信号,进程能够指定处置函数,由该函数来处置。

第二种方式是,忽略某个信号,对该信号不做任何处置,就象未发生过一样。

第三种方式是,对该信号的处置保留系统的默许值,这种缺省操作,对大部份的信号的缺省操作是使进程终止。

进程通过系统挪用signal()来指定进程对某个信号的处置行为。

本系统挪用的头文件为:

#include<>

系统挪用格式:

signal(sig,function)

int sig;

void(*function)()

其中sig用于指定信号的类型,sig为0那么表示没有收到任何信号。

sig的值是以下之一:

SIGHUP挂起1

SIGINT键盘按Ctrl-c键或Ctrl-break键2

SIGQUIT键盘按quit键(Ctrl-\)3

SIGILL非法指令4

SIGTRAP跟踪中断5

SIGIOT/SIGABRTIOT指令或挪用abort函数生成的信号6

SIGBUS总线错7

SIGFPE浮点运算溢出8

SIGKLL要求终止进程9

SIGUSR1用户概念信号#110

SIGSEGV段违法11

SIGUSR2用户概念信号#212

SIGPIPE向无读者管道上写13

SIGALRM按时器告警,时刻到14

SIGTERMkill发出的软件终止信号15

SIGCHLD子进程死17

SIGPWR电源故障30

function是该进程中的一个函数地址,function的说明如下:

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

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

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

function还能够是:

(1)SIG_IGN忽略那个信号.

(2)SIG_DFL恢复对那个信号的默许处置

有关系统挪用signal()的例子:

例1():

#include<>

#include<>

#include<>

main(){

signal(SIGINT,SIG_IGN);/*忽略那个信号*/

printf(”hello!

\n”);

sleep(10);

printf(”world”);

}

例2():

#include<>

#include<>

#include<>

intcatch(intsig);

main(){

signal(SIGINT,catch);

printf(”hello!

\n”);

sleep(10);

printf(”world\n”);

}

intcatch(intsig){

printf(”catchsignal.\n”);

}

例3:

()下面程序的功能:

对Ctrl-c组合键的响应是输出一条消息而不是终止运行;程序将在用户第二次按下Ctrl-c组合键后终止。

#include<>

#include<>

#include<>

voidouch(intsig)

{

printf("Igotsignal%d\n",sig);

signal(SIGINT,SIG_DFL);/*恢复对那个信号的默许处置*/

}

intmain()

{

signal(SIGINT,ouch);

while

(1)

{

printf("HelloWorld!

\n");

sleep

(1);

}

}

请运行上面程序并分析运行结果。

(提示:

当用户通过按下Ctrl-c组合键给出SIGINT信号时,函数ouch将被挪用,程序会在函数ouch终止后继续执行,但信号处置动作恢复为默许动作,当程序接收到第二个SIGINT信号时,程序采纳默许动作,终止执行。

例4:

通过编译:

gcc–osignaltest0

取得可执行文件:

signaltest0

后台执行该文件:

(在文件名后面加上&)

/*或者写成:

kill-91586*/

/*向进程发送SIGHUP信号*//*向进程发送SIGINT信号*//*向进程发送SIGQUIT信号*/

前台执行该文件:

/*或者写成:

kill-91612*/

/*按Ctrl+C组合键得到的结果*/

/*按Ctrl+\组合键得到的结果*/

/*按Ctrl+Z组合键得到的结果*/

六、raise()

raise()系统挪用用于向自身发送信号。

本系统挪用的头文件为:

#include<>

系统挪用格式:

intraise(intsig);

挪用成功时返回0,犯错时返回-1。

能够看出,raise()能够通过kill()实现,raise(sig)等价于kill(getpid(),sig);

7、alarm()

alarm()系统挪用的功能是设置一个按时器,当按时器计时抵达时,将发出信号SIGALRM给进程。

若是不忽略或捕捉此信号,它的默许操作是终止挪用该alarm函数的进程。

本系统挪用的头文件为:

#include<>

系统挪用格式:

unsignedintalarm(unsignedintseconds);

若是参数seconds为0,那么之前设置的闹钟会被取消,并将剩下的时刻(剩余的秒数)返回,若是之前未设置闹钟,那么返回0。

注意:

在利历时,alarm()只设置为发送一次信号,若是要多次发送,就要多次挪用alarm()函数。

八、pause()

pause()系统挪用的功能是使当前进程暂停,进入眠眠状态,直到被信号所中断。

本系统挪用的头文件为:

#include<>

系统挪用格式:

intpause(void);

该函数只返回-1。

程序范例:

编译并运行该程序,若是去掉代码中的signal()函数挪用,结果是什么?

四、参考程序:

参考程序1:

#include""

#include""

#include""

#include""

intwait_mark;

voidwaiting();

voidstop(intsig);

main()

{

intp1,p2;

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

if(p1>0){/*父进程的处置*/

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

if(p2>0){/*父进程的处置*/

wait_mark=1;

getchar();

kill(p1,SIGUSR1);/*向子进程p1发出信号SIGUSR1*/

kill(p2,SIGUSR2);/*向子进程p2发出信号SIGUSR2*/

wait(0);/*同步*/

wait(0);

printf("Parentprocessiskilled!

!

\n");

exit(0);

}

else{/*子进程p2的处置*/

wait_mark=1;

signal(SIGUSR2,stop);

waiting();/*等待信号SIGUSR2*/

sleep

(1);

lockf((int)stdout,1,0);/*用上锁的方式实现互斥*/

printf("Childprocess2iskilledbyparent!

!

\n");

lockf((int)stdout,0,0);

/*模拟子进程P2被kill时进程的工作*/

exit(0);

}

}

else{/*子进程p1的处置*/

wait_mark=1;

signal(SIGUSR1,stop);

waiting();/*等待信号SIGUSR1*/

sleep

(1);

lockf((int)stdout,1,0);/*用上锁的方式实现互斥*/

printf("Childprocess1iskilledbyparent!

!

\n");

lockf((int)stdout,0,0);

/*模拟子进程P1被kill时进程的工作*/

exit(0);

}

}

voidwaiting()

{

while(wait_mark!

=0);

}

voidstop(intsig)

{

printf("Igotsignal%d\n",sig);

wait_mark=0;

}

运行程序,观看运行结果,并分析。

参考程序2:

#include<>

#include<>

#include<>

main()

{

intp1,p2,i;

FILE*fp;

fp=fopen("","w");/*以写的方式打开文件*/

if(fp==NULL)

{

printf("Failtocreatefile");

exit(-1);

}

while((p1=fork())==-1);/*创建子进程p1*/

if(p1==0)

{

lockf((int)fp,1,0);/*加锁*/

for(i=0;i<1000;i++)

fprintf(fp,"Child1%d\n",i);

lockf((int)fp,0,0);/*解锁*/

}

else

{

while((p2=fork())==-1);/*创建子进程p2*/

if(p2==0)

{

lockf((int)fp,1,0);/*加锁*/

for(i=0;i<1000;i++)

fprintf(fp,"Child2%d\n",i);

lockf((int)fp,0,0);/*解锁*/

}

else

{

wait(0);

wait(0);

lockf((int)fp,1,0);/*加锁*/

for(i=0;i<1000;i++)

fprintf(fp,"Parent%d\n",i);

lockf((int)fp,0,0);/*解锁*/

fclose(fp);/*关闭文件*/

}

}

}

四.试探题

在本实验中,进程的同步和互斥是如何实现的?

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

当前位置:首页 > 经管营销 > 经济市场

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

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