操作系统实验实验Word文档格式.docx
《操作系统实验实验Word文档格式.docx》由会员分享,可在线阅读,更多相关《操作系统实验实验Word文档格式.docx(29页珍藏版)》请在冰豆网上搜索。
b'
和字符'
c'
。
试观察记录屏幕上的显示结果,并分析原因。
2、修改上述程序,每一个进程循环显示一句话。
子进程显示'
daughter…'
及'
son……'
,父进程显示'
parent……'
,观察结果,分析原因。
三、实验步骤
代码:
#include<
stdio.h>
main()
{
intp1,p2;
while((p1=fork())==-1);
/*创建子进程p1*/
if(p1==0)putchar('
);
else
{
while((p2=fork())==-1);
/*创建子进程p2*/
if(p2==0)putchar('
elseputchar('
}
运行结果:
bca,bac,abc,……都有可能。
intp1,p2,i;
while((p1=fork())==-1);
if(p1==0)
for(i=0;
i<
10;
i++)
printf("
daughter%d\n"
i);
else
while((p2=fork())==-1);
if(p2==0)
printf("
son%d\n"
parent%d\n"
结果:
parent…
son…
daughter..
或parent…
daughter…等
四、分析原因
除strace外,也可用ltrace-f-i-S./executable-查看以上程序执行过程。
1、从进程并发执行来看,各种情况都有可能。
上面的三个进程没有同步措施,所以父进程与子进程的输出内容会叠加在一起。
输出次序带有随机性。
2、由于函数printf()在输出字符串时不会被中断,因此,字符串内部字符顺序输出不变。
但由于进程并发执行的调度顺序和父子进程抢占处理机问题,输出字符串的顺序和先后随着执行的不同而发生变化。
这与打印单字符的结果相同。
五、思考题
(1)系统是怎样创建进程的?
linux系统创建进程都是用fork()系统调用创建子进程。
Init程序以/etc/inittab为脚本文件来创建系统的新进程的。
新进程还克以创建新进程。
创建新进程是通过克隆老进程或当前进程来创建的。
新进程的创建实用系统调用sys_fork()或sys_clone(),并且在内核模式下完成。
在系统调用结束时,系统从物理内存中分配一个心的task_struct()数据结构和进程堆栈,同时获得一个唯一的标示此进程的标识符。
通过FORK函数调用促使内核创建一个新的进程,该进程是调用进程的一个精确的副本。
新创建的进程为子进程,调用的FORK进程为父进程,而且创建出来的是两个副本,即,两个进程,但他们互不干扰。
(2)当首次调用新创建进程时,其入口在哪里?
首次创建进程时,入口在进程1那里。
(二)进程的控制实验
1、掌握进程另外的创建方法
2、熟悉进程的睡眠、同步、撤消等进程控制方法
1、用fork()创建一个进程,再调用exec()用新的程序替换该子进程的内容
2、利用wait()来控制进程执行顺序
三、参考程序
#include<
unistd.h>
main()
intpid;
pid=fork();
/*创建子进程*/
switch(pid)
case-1:
/*创建失败*/
forkfail!
\n"
exit
(1);
case0:
/*子进程*/
execl("
/bin/ls"
"
ls"
-1"
-color"
NULL);
execfail!
default:
/*父进程*/
wait(NULL);
/*同步*/
lscompleted!
exit(0);
}
四、运行结果
五、思考
(1)可执行文件加载时进行了哪些处理?
解:
可执行文件加载时首先是创建一个新进程的fork系统调用,然后用于实现进程自我终止的exit系统调用;
改变进程原有代码的exec系统调用;
用于将调用进程挂起并等待子进程终止的wait系统调用;
获得进程标识符的getpid系统调用等处理过程。
(2)什么是进程同步?
wait()是如何实现进程同步的?
进程同步是指对多个相关进程在执行次序上进行协调,以使并发执行的主进程之间有效地共享资源和相互合作,从而使程序的执行具有可在现行。
首先程序在调用fork()机那里了一个子进程后,马上调用wait(),使父进程在子进程调用之前一直处于睡眠状态,这样就使子进程先运行,子进程运行exec()装入命令后,然后调用wait(0),使子进程和父进程并发执行,实现进程同步。
(三)进程互斥实验
实验目的
1、进一步认识并发执行的实质
2、分析进程竞争资源的现象,学习解决进程互斥的方法
实验内容
1、修改实验
(一)中的程序2,用lockf()来给每一个进程加锁,以实现进程之间的互斥
2、观察并分析出现的现象
main( )
while((p1=fork())==-1);
if(p1==0)
lockf(1,1,0);
/*加锁,这里第一个参数为stdout(标准输出设备的描述符)*/
for(i=0;
lockf(1,0,0);
/*解锁*/
while((p2=fork())==-1);
if(p2==0)
/*加锁*/
{
lockf(1,1,0);
parent%d\n"
lockf(1,0,0);
运行结果
或parent…
daughter…
大致与未上锁的输出结果相同,也是随着执行时间不同,输出结果的顺序有所不同。
上述程序执行时,不同进程之间不存在共享临界资源(其中打印机的互斥性已由操作系统保证)问题,所以加锁与不加锁效果相同。
(四)守护进程实验
写一个使用守护进程(daemon)的程序,来实现:
1,创建一个日志文件/var/log/Mydaemon.log
2,每分钟都向其中写入一个时间戳(使用time_t的格式)
注意:
要root权限才能在/var/log创建文件。
守护神程序:
time.h>
main(){
time_tt;
//建立time_t格式变量
FILE*fp;
//建立文件
fp=fopen("
/var/log/Mydaemon.log"
a"
//打开文件
pid_tpid;
//守护神
pid=fork();
if(pid>
0){
Daemononduty!
exit(0);
elseif(pid<
Can'
tfork!
exit(-1);
while
(1){
if(fp>
=0){
sleep(60);
//等待一分钟再往文件中写入时间戳
t=time(0);
fprintf(fp,"
Thecurrenttimeis%s\n"
asctime(localtime(&
t)));
fclose(fp);
//关闭文件
进程通信
(一)信号机制实验
1、了解什么是信号
2、熟悉LINUX系统中进程之间软中断通信的基本原理
1、编写程序:
用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上来的中断信号(即按^c键);
捕捉到中断信号后,父进程用系统调用kill()向两个子进程发出信号,子进程捕捉到信号后分别输出下列信息后终止:
Childprocess1iskilledbyparent!
Childprocess2iskilledbyparent!
父进程等待两个子进程终止后,输出如下的信息后终止:
Parentprocessiskilled!
2、分析利用软中断通信实现进程同步的机理
参考程序
signal.h>
voidwaiting(),stop();
intwait_mark;
intp1,p2,stdout;
while((p1=fork())==-1);
if(p1>
0)
while((p2=fork())==-1);
if(p2>
wait_mark=1;
signal(SIGINT,stop);
/*接收到^c信号,转stop*/
waiting();
kill(p1,16);
/*向p1发软中断信号16*/
kill(p2,17);
/*向p2发软中断信号17*/
wait(0);
/*同步*/
else
signal(17,st