华工操作系统实验3实验报告及实验步骤详解Word下载.docx
《华工操作系统实验3实验报告及实验步骤详解Word下载.docx》由会员分享,可在线阅读,更多相关《华工操作系统实验3实验报告及实验步骤详解Word下载.docx(9页珍藏版)》请在冰豆网上搜索。
fork()用于创建新的进程,所创建进程为当前进程的子进程,可以通过fork()函数的返回值来控制进程是在父进程中还是在子进程中。
如果运行在父进程中,则返回PID为子进程的进程号,如果在子进程中,则返回的PID为0。
2.简述信号量的作用及使用方法。
作用:
多进程资源共享时,使用信号量,避免产生死锁。
使用方法:
信号量是一个整数;
大于或等于0时代表可供并发进程使用的资源实体数;
小于0时代表正在等待使用临界区的进程数;
用于互斥的信号量初始值应大于0;
只能通过P、V原语操作而改变。
【实验环境】
运行电脑系统:
win7
所用软件:
VMware9.0.0.0
模拟系统:
Ubuntu
实验内容
【实验过程】
(实验步骤、记录、数据、分析)
1、创建新的进程:
使用fork()函数
查看运行进程&
换出某个进程:
使用execl换出进程,并且用PS来替换以达到查看进程的效果
杀死运行进程:
在父进程后使用kill函数
代码:
#include<
stdio.h>
sys/types.h>
unistd.h>
#include<
signal.h>
intmain()
{
pid_tpid;
pid=fork();
//创建进程
if(pid==0)
{
printf("
Iamthechild,mypidis%d!
\n"
getpid());
execl("
/bin/ps"
"
ps"
r"
NULL);
//查看进程和替换进程
}
else
sleep
(2);
Iamtheparent,mypidis%d,mychildpidis%d!
getpid(),pid);
kill(getpid(),SIGTERM);
//杀死进程
Notkill"
);
}
运行结果:
结果分析:
如图所示,在调用了fork()函数后,程序先创建了子进程,然后进程被execl替换成ps,显示出了当前正在运行的进程,最后父进程运行,由于执行了kill()函数,所以后面的printf里的内容并未打印出来。
2.采用写者优先重写P94的读者-写者问题,并通过一个读写序列,将算法与读者优先算法进行比较。
#include"
unistd.h"
stdio.h"
stdlib.h"
signal.h"
pthread.h>
pthread_mutex_trmutex;
//控制对rc的访问
pthread_mutex_twmutex;
//控制对wc的访问
pthread_mutex_treadDB;
//用于写进程对读进程的互斥
pthread_mutex_twriteDB;
//用于读进程对写进程互斥和写进程之间的互斥
intrc=0;
//正在读或者即将读的进程数目
intwc=0;
//即将写的进程数目
pthread_tntid;
voidread_data_base()
pthread_ttid;
tid=pthread_self();
printf("
reading,tidis%d\n"
(unsignedint)tid);
sleep
(2);
voidwrite_data_base()
writing,tidis%d\n"
void*reader(void*ptr)
readercomeing,readytoread...\n"
);
pthread_mutex_lock(&
wmutex);
pthread_mutex_unlock(&
rmutex);
rc=rc+1;
if(rc==1)
pthread_mutex_lock(&
readDB);
read_data_base();
rc=rc-1;
if(rc==0)
pthread_mutex_unlock(&
return((void*)0);
void*writer(void*ptr)
writercomeing,readytowrite...\n"
wc=wc+1;
if(wc==1)
writeDB);
write_data_base();
wc=wc-1;
if(wc==0)
intmain(void)
pthread_mutex_init(&
wmutex,0);
rmutex,0);
writeDB,0);
readDB,0);
pthread_create(&
ntid,NULL,reader,NULL);
ntid,NULL,writer,NULL);
pthread_exit((void*)pthread_self());
exit(0);
写者优先就是说当等待队列中既有读者又有写者时,优先完成写操作,从结果来看,代码是正确的。
对比读者优先和写者优先,可以看出,写者优先会比读者优先慢一些,这是因为写操作是不能同时运行,会降低并行度。
所以读者优先的效率会略高于写者优先。
3、编写一个使用线程并共享一个公共缓冲区的生产者-消费者问题。
但是,不要使用信号量或任何其他用来保护共享数据结构的同步原语。
直接让每个线程在需要访问时就访问。
使用sleep和wakeup来处理满和空的条件。
观察需要多长时间会出现比较严重的竞争条件。
例如,可以让生产者一会儿打印一个数字,每分钟打印不要超过一个数字,因为I/O会影响竞争条件。
(课本98页作业题53)
#defineMAX1000000000
#defineN5//缓冲区中的槽数目
pthread_mutex_tthe_mutex;
pthread_cond_tcondc,condp;
intcount=0;
void*producer(void*ptr)
inti;
for(i=1;
i<
=MAX;
i++)
if(count==N)
pthread_cond_wait(&
condp,&
the_mutex);
count=count+1;
sleep
(1);
if(i%60==0)
printf("
running...%d\n"
count);
if(count==1)
pthread_cond_signal(&
condc);
void*consumer(void*ptr)
i<
if(count==0)
condc,&
count=count-1;
if(count==N-1)
condp);
pthread_tpro,con;
the_mutex,0);
pthread_cond_init(&
condc,0);
condp,0);
con,NULL,consumer,NULL);
pro,NULL,producer,NULL);
return0;
结果(运行了15分钟左右,此时程序并未停止,但却不再打印):
代码会可能会出现竞争条件,其原因是对count的访问未加限制。
有可能出现如下情况:
缓冲区为空,消费者刚刚读取count的值发现它为0.此时调度程序决定暂停消费者并启动运行生产者。
生产者向缓冲区加入一个数据项,count加1。
现在count的值变成了1。
它推断认为由于count刚才为0,所以消费者此时一定在睡眠,此时生产调用pthread_cond_signal(&
condc)来唤醒消费者。
但是,消费者此时在逻辑上并未睡眠,所以信号丢失。
当消费者下次运行时,它将测试先前读到的conut值,发现它为0,于是睡眠。
生产者迟早会填满整个缓冲区,然后睡眠。
这样一来,两个线程将永远眨眼下去。
实验总结
指导教师评语及成绩
评语:
成绩:
指导教师签名:
批阅日期: