【操作系统】进程互斥验证性实验报告

7 篇文章 1 订阅

操作系统#进程互斥验证性实验报告

正文

一、 实验目的

  • 父进程和两个子进程分别连续向共享文件中写入3行字符串。多次运行程序,观察共享文件内容。
  • 修改程序1,先去掉第一个子进程的lock/unlock调用,观察分析共享文件中,3个进程写入字符串的次序,解释原因。
  • 去掉所有lock/unlock调用。多次运行程序,观察分析共享文件中,3个进程写入字符串的次序,解释原因。

二、 实验设备

  • Windows 操作系统
  • VMware workstation

三、 实验说明

  • lockf(files,function,size) :用作锁定文件的某些段或者整个文件。
    其中:files是文件描述符;参数function可以取以下值:F_LOCK:锁定一个区域。F_ULOCK:解除锁定。参数size指明了从文件当前位置开始的一段连续锁定区域的长度,当size为0时,锁定记录将由当前位置一直扩展到文件尾。
    2.lseek(files, offset, whence): 控制文件的读写位置. 参数files 为已打开的文件描述词, 参数offset 为根据参数whence来移动读写位置的位移数.
    欲将读写位置移到文件开头时: lseek(files, 0, SEEK_SET);
    read:读文件
    int read(int fd,void *buf,size_t nbytes)
    3.从文件描述符fd所代表的文件中读取nbytes 个字节,到buf指定的缓冲区内。所读取的内容从当前的读/写指针所指示的位置开始,这个位置由相应的打开文件描述中的偏移值(off_set)给出,调用成功后文件读写指针增加实际读取的字节数。
    返回: -1:错误;0:文件偏移值是在文件结束处;
    整数:从该文件复制到规定的缓冲区中的字节数。通常这个字节数与所请求的字节数相同。
    open:打开一个文件
    int open(char *path,int flags,mode_t mode);
    其中:参数path 是指向所要打开的文件的路径名指针。
    参数falgs 规定如何打开该文件,它必须包含以下值之一 :
    O_RDONLY,只读打开 ;
    O_WRONLY,只写打开 ;
    O_RDWR,读/写打开;
    O_CREAT,当文件不存在时创建文件,需参数mode;O_APPEND,不论当前文件位置在何处,将文件指针移至文件尾,为write添加数据到文件;O_TRUNC,当以可写的方式成功打开普通文件时,截断该文件的长度为0。参数mode 规定对该文件的访问权限。
    write:写文件
    int write(int fd,void *buf,size_t nbytes)
    该调用从buf所指的缓冲区中将nbytes 个字节写到描述符fd所指的文件中。
    close:关闭文件
    int close(int fd);
    每打开一个文件,系统就给文件分配一个文件描述符,同时为打开文件描述符的引用计数加1。Linux文件系统最多可以分配255个文件描述符。当调用close()时,打开文件描述符的引用计数值减1,最后一次对close()的调用将使应用计数值为零。
    虽然当一个进程结束时,任何打开的文件将自动关闭,明显地关闭任何打开的文件是良好的程序设计习惯。

四、 实验步骤

#include<fcntl.h>
#include<stdio.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/stat.h> 
#include <stdlib.h>
#include <string.h>
int fatal (const char* info)
{
  perror (info);
  exit (1);
}
int lock(int fd)
{
lseek(fd,0,SEEK_SET);
if(lockf(fd,F_LOCK,0)==-1)
fatal("lockf()");
return 0;
}
int unlock(int fd)
{
lseek(fd,0,SEEK_SET);
if(lockf(fd,F_ULOCK,0)==-1)
 fatal("unlockf()");
return 0;
}
int main()
{
int fd;   
int p1,p2,i;
char str[20];
if((fd=open("result.txt",O_RDWR|O_APPEND|O_CREAT,0666))<0)
   fatal("open");  
write(fd,"=========\n",10);
while((p1=fork( ))== -1);       /*创建子进程女儿进程*/
if (女儿进程==0)
  {
    lock(fd);             /*加锁*/
    for(i=0;i<3;i++)
    {
     sprintf(str,"daughter %d\n",i);     
     write(fd,str,strlen(str));
     sleep(1);
     }
     unlock(fd);              /*解锁*/
   }
else
{
   while((p2=fork( ))==-1);  /*创建子进程儿子进程*/
   if (儿子进程==0)
   {
     lock(fd);             /*加锁*/
    for(i=0;i<3;i++)
    {
     sprintf(str,"son %d\n",i);
     write(fd,str,strlen(str));
     sleep(1);
    }
    unlock(fd);              /*解锁*/
    }
else
   {
    lock(fd);             /*加锁*/
    for(i=0;i<3;i++)
     {
     sprintf(str,"parent %d\n",i);
     write(fd,str,strlen(str));
      sleep(1);
     }
     unlock(fd);              /*解锁*/
     wait(NULL);
     wait(NULL);
   }
}
close(fd);
}


五、 结果分析与总结

1.父亲女儿儿子进程中都有lock(fd),三者之间都相处排斥,因而等一个进程输出完毕后,解锁,下一个进程上锁进行输出,多次运行,效果一致,输出如图所示。
在这里插入图片描述
在这里插入图片描述

2.注释掉女儿进程进程中的lock(fd),则现在只有儿子进程中有lock(fd)与最后的else{}中含有lock(fd),从而两者互斥,儿子进程与两者不互斥,输出如图所示。
在这里插入图片描述

在这里插入图片描述

注释掉所以进程中的lock(fd),则他们之间没有任何的互斥关系,因而按照代码顺序,输出如图所示。
2021年4月23日

  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

君问归期魏有期

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值