广东海洋大学操作系统.实验(1)

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

班级:计科1141 学号:201411621110 姓名:邓超荣

实验一进程同步与互斥

实验目的了解多进程并发执行时因控制不当而导致的运行结果不确定的竞争条件现象、以及消除竞争条件所采取的措施。

实验内容

有一个数据文件,名字是data,其中存放了一个十进制正整数。现有一个程序,该程序读出文件data中的数据、将其加一、再将结果更新到data之中,上述动作重复进行一百万次。如下给出完成上述功能的源程序:

01 #include

02 #include

03 #include

04 #include

05 #include

06 #include

07 #include

08 int main()

09 {

10 int num, fd,i;// num变量用于存放从buff转换而来的二进制形式的整数

//fd是打开data文件之后的描述符,用于下文对data文件的读写操作

11 char buff[100];// 定义的buff字符数组用于存放从文件中读出的数字字符形式的整数

12 fd = open("data", O_RDWR);//打开文件

13 if(fd<=0){//如果文件不存在

14 printf("open error\n");

15 return 1;

16 }

17 for(i=1;i<=1000000;i++){//循环一百万次循环循环

18 lseek(fd, 0, SEEK_SET);// 将文件的读写指针归零

19 int len = read(fd, buff, 100);//len存放从文件读入的数字符的长度

20 buff[len]='\0';//在字符串后添加空格代表结束

21 num = atoi(buff);// 调用atoi函数,将字符串转换为二进制形式,并存放在num

22 sprintf(buff, "%d\n", num + 1);//num+1,循环10000次后就是1000000+num

23 lseek(fd, 0, SEEK_SET);// 将文件的读写指针归零即置于起始字节之处

24 write(fd, buff,strlen(buff));//将更新后的数重新写入文件中

25 }

26 close(fd);//关闭文件

27 return 0;//返回

28 }

问题:

1.请在linux中编译、链接、执行这个程序。如果该程序只作为单个进程执行,请观察运

行结果,并分析代码。

首先向data文件中输入1107,并进行保存。

该程序分析如下:

第10行中定义变量num存放从buff的字符串中转换而来的二进制形式的整数,变量fd存放打开data文件之后的描述符;第11行中定义长度为100的字符数组,用于存放从data文件中读出的数字字符形式的整数;第12行打开data文件;第13-16行判断文件是否打开,如果没有,则输出open error提示;第17-25行,循环1000000次操作,第18行,在每次循环都将文件的读写指针指向文件的起始位置;第19行,len保存读入字符串的长度;第20行,在字符串结尾加入空格符以示结束;第21行,调用atoi()函数,将buff的字符串转变为二进制数;第22行,对转变得二进制数进行+1操作;第23行,把文件的读写指针至于文件起始位置;第24行,将更新的数据重新写回data文件中。如此循环一百万次,相当于data中存放的数据加上一百万,所以得出图中所示结果。

2.在不改变程序代码的情况下,怎样把上述程序作为多个进程来并发执行?请观察并发执行情况下的运行结果,分析运行结果错误的具体原因。

答:要实现多进程并发执行,可多个窗口对同一程序进行运行。

由于data文件初始值为1234,所以两个进程在并发执行的情况下,正确结果应该为2001234,可是最后结果却为1509625。显然与正确结果不符。此主要原因在于,在两个进程同时执行的时候,可能会在同一时间对num进行操作,导致重读,如原本进程1对2加1后为3,进程而对3加1后为4.而现实中可能产生的情况是进程1和进程2同时对2进行加1操作,所以得到最终结果是3而不是4;另一种情况是,进程1已进行了加1操作但在保存到文件之前,进程2执

行到读取文件数据,因此,进程2读取的还是原本数据,进行加1操作后仍然是进程1执行操作后的数据。所以当多进程并发执行时,最后得出的结果与预想中的结果不同。

3.请修改上述代码,采用上锁方式,以保证并发执行时运行结果的正确性,并分析得到了正确结果的原因。

修改后,代码如下:

#include

#include

#include

#include

#include

#include

#include

int main()

{

struct flock fl;//定义结构体flock,设置锁

int num, fd,i;

char buff[100];

fd = open("data", O_RDWR);

if(fd<=0){

printf("open error\n");

return 1;

}

fl.l_whence = SEEK_SET;//设置文件读写位置

fl.l_start = 1;//开始位置为1

fl.l_len = 1;//长度为1

fl.l_pid = getpid();//获取进程

for(i=1;i<=1000000;i++){

fl.l_type = F_WRLCK;//对文件加锁

fcntl(fd, F_SETLKW, &fl);//对文件逐个扫描

lseek(fd, 0, SEEK_SET);

int len = read(fd, buff, 100);

buff[len]='\0';

num = atoi(buff);

sprintf(buff, "%d\n", num + 1);

lseek(fd, 0, SEEK_SET);

write(fd, buff,strlen(buff));

fl.l_type = F_UNLCK;//解锁文件

fcntl(fd, F_SETLKW, &fl);

}

相关文档
最新文档