Chinaunix

标题: 一个linux进程实验问题 [打印本页]

作者: 乌龙张    时间: 2008-10-22 20:25
标题: 一个linux进程实验问题
以下为linux环境下的操作系统“进程控制”实验相关部分:
#include<stdio.h>
main()
{
&nbsp;&nbsp;&nbsp;&nbsp;int p1,p2,i;
&nbsp;&nbsp;&nbsp;&nbsp;if(p1=fork())
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lockf(1,1,0);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(i=0;i<5000;i++)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("child %d\n",i);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lockf(1,0,0);
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(p2=fork())
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lockf(1,1,0);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(i=0;i<5000;i++) printf("son %d\n",i);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lockf(1,0,0);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lockf(1,1,0);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(i=0;i<5000;i++) printf("daughter %d\n",i);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lockf(1,0,0);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
}

这个实验的目的是想让学生体会到加上lockf的作用,可以互斥的显示在屏幕上。即:完全输出child后完全输出son或者再完全输出daughter。
但是真正做实验的时候,发现三个进程还是并发的把结果显示在屏幕上,即:child输出到4000多行,就又开始输出son了。。。。
请问这是为什么呢?错在哪里呢?lockf()不就是加锁,能够保证互斥吗?

请高手回答,谢谢!

[ 本帖最后由 duanjigang 于 2008-10-23 06:57 编辑 ]
作者: believetruelove    时间: 2008-10-22 21:23
帮顶一下,我也想知道答案!
作者: duanjigang    时间: 2008-10-23 06:59
这个实验的目的是想让学生体会到加上lockf的作用可以互斥的显示在屏幕上。即:完全输出child后完全输出son或者再完全输出daughter。但是真正做实验的时候,发现三个进程还是并发的把结果显示在屏幕上,即:child输出到4000多行,就又开始输出son了。。。。
请问这是为什么呢?错在哪里呢?lockf()不就是加锁,能够保证互斥吗?

首先:体会到加上lockf的作用,说得很不明白,lockf是实现什么作用的,进程之间互斥还是线程之间互斥,看代码应该是进程之间实现互斥的。
其次:你的目的是先child输出,再son输出,但是请仔细分析代码,即使你的lock有效,这样的代码结构能打到效果吗?fork()返回之后子进程和父进程就开始并发执行了,谁能先调用lockf在原理上说是不能确定的。还有:“lockf不就是加锁,能保证互斥吗?”不明白你说的意思,太混沌了。
举个例子,如果你的目的是实现进程之间的互斥,却采用了线程互斥的技术实现了lockf,那么每个进程都在lockf,是没有一点作用的,当然我猜测你的lockf很可能就是在用flock方法。
楼主先把问题说清楚吧,呵呵

[ 本帖最后由 duanjigang 于 2008-10-23 07:10 编辑 ]
作者: 乌龙张    时间: 2008-10-23 22:03
谢谢楼上朋友。
经过fock之后是有多个进程并发执行。
我的目的并不是“先child输出,再son输出”,进程并发执行,谁先被输出都有可能。
我是认为加上了lockf之后,如果一个进程先得到执行,应该连续输出500行(不会被打断输出),而我在做实验的时候,输出child的时候,输出400多行child的时候被son的输出打断了。
我不明白为什么会被打断?
还请各位朋友继续帮助我,谢谢!
作者: Roemer    时间: 2008-10-23 22:38
lockf返回值是什么?成功了吗?
作者: duanjigang    时间: 2008-10-24 06:51
原帖由 乌龙张 于 2008-10-23 22:03 发表
谢谢楼上朋友。
经过fock之后是有多个进程并发执行。
我的目的并不是“先child输出,再son输出”,进程并发执行,谁先被输出都有可能。
我是认为加上了lockf之后,如果一个进程先得到执行,应该连续输出500行 ...

我在上次回复中已经提到了,你的lockf是个什么咚咚?能实现进程互斥吗?这个你还没有回答
作者: 乌龙张    时间: 2008-10-24 09:01
原帖由 duanjigang 于 2008-10-24 06:51 发表

我在上次回复中已经提到了,你的lockf是个什么咚咚?能实现进程互斥吗?这个你还没有回答


lockf(files,function,size)

int files,function;

long size;

其中:files是文件描述符,0代表键盘,1代表显示器;

function是锁定和解锁,1表示锁定,0代表解锁;

size是锁定或解锁的字节数,为0表示从文件的当前位置到文件尾
作者: duanjigang    时间: 2008-10-24 09:15
我刚刚测试了下,没有问题的
child,son,和daughter的打印都是分开的,没有混在一起。
我的系统是linux AS4
2.6.9-5.ELsmp
作者: duanjigang    时间: 2008-10-24 09:17
你把结果重定向到文件中检查下
  1. test_prog > result.txt
复制代码

然后检查0-5000行,5000-10000行,10000-15000行是否有别的字符串
作者: 乌龙张    时间: 2008-10-24 10:11
谢谢朋友。
我是用GCC编译之后,用./a.out |more来观看结果的,看到0-5000行里并不是一种字符串,是两种混杂在一起。
所以我就是想不明白呢。
作者: 乌龙张    时间: 2008-10-24 10:39
原帖由 duanjigang 于 2008-10-24 09:17 发表
你把结果重定向到文件中检查下
test_prog > result.txt

然后检查0-5000行,5000-10000行,10000-15000行是否有别的字符串



我又用了结果重定向到一个文件中观看的,还是有打断呢。第一个字符串完整连续的显示了5000行,第二个字符串与第三个字符串显示被打断,有了混合。
出现以下这种情况:

未命名.jpg (5.17 KB, 下载次数: 34)

未命名.jpg

作者: tyz    时间: 2008-10-24 11:01
同问
是不是那个锁定进程的函数有问题
作者: timespace    时间: 2008-10-24 12:46
呵呵,开始还以为你真的直接从终端屏幕捕捉了该现象!
原来经过重定向啊,那么一切都容易解释了: ... | proc或者 ... > file,标准输出重定向后变为全缓存,此时输出结果用术语说就是unspecified或undefined。文件锁切忌和stdio相关函数混合使用,尤其是输出为全缓存时,建议配合read或write使用。总之,文中lock(1,1,0)锁定标准输出确实成功了,但是由于全缓存的作用,最后部分出现交叉,如果没有重定向,标准输出默认是行缓存,结果不会交叉。
作者: 乌龙张    时间: 2008-10-25 12:47
原帖由 timespace 于 2008-10-24 12:46 发表
呵呵,开始还以为你真的直接从终端屏幕捕捉了该现象!
原来经过重定向啊,那么一切都容易解释了: ... | proc或者 ... > file,标准输出重定向后变为全缓存,此时输出结果用术语说就是unspecified或undefined。 ...


可是结果十分庞大,屏幕很快翻到最后一页,如何仔细看结果呢?
作者: timespace    时间: 2008-10-25 15:24
原帖由 乌龙张 于 2008-10-25 12:47 发表


可是结果十分庞大,屏幕很快翻到最后一页,如何仔细看结果呢?


可以直接通过文件输出结果,文件缓存设置为行缓存,与标准输出效果一样,但看结果方便。
作者: 乌龙张    时间: 2008-10-26 18:24
原帖由 timespace 于 2008-10-25 15:24 发表


可以直接通过文件输出结果,文件缓存设置为行缓存,与标准输出效果一样,但看结果方便。


我就是用的: ./a.out >result.txt,就是输出到文件呀,可是打开此文件看到结果还是有交叉。
作者: Au_Hank    时间: 2008-10-26 20:41
我在 2.4.20-8实验了, 没有问题啊
作者: 乌龙张    时间: 2008-10-26 20:43
原帖由 timespace 于 2008-10-25 15:24 发表


可以直接通过文件输出结果,文件缓存设置为行缓存,与标准输出效果一样,但看结果方便。


如何设置为行缓存呢?
作者: yjh777    时间: 2008-10-26 21:11
原帖由 乌龙张 于 2008-10-26 20:43 发表


如何设置为行缓存呢?


你改用标准错误吧,标准错误默认是非缓冲的  lock 1 => lock 2   printf( => fprintf(stderr,
作者: piapia2009    时间: 2008-10-27 23:17
提几点自己的看法:
1、代码写的很不规范,fork函数一般都要判断 大于0 小于0 等于0三种情况,还有lockf也要做判断;
2、我测试了一下,child和son daughter谁先谁后都有可能的,但都会一直走完
3、可以考虑用freopen进行重定向




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2