初学Linux IPC,多指教。。。

xiaowai0219 2010-04-14 10:40:27
接触Linux编程一个月的样子,照着Linux编程入门到精通在学,现学到了IPC机制。ipc过了一遍了,感觉有的繁,里面的结构有点多,有点理不清头绪。准备再探。如果有对Linux IPC熟悉的,请给点意见。如,学这个东西需要注意的地方,重点要掌握的地方之类的。如果可以的话,可以分享自身成功的经验,有问题的也可以提出来一起学习。。。

下面是我学进程时遗留下来的问题,如果可以也给我一并解决了吧(我就发了三个帖子,之前两个都是这个问题,还没解决彻底)
pid_t pid;
void handle(int signo){
/*****************************问题所在*************************************************
*多执行几次pid会出现不同的结果0,或者子进程的pid
*一个是fork返回到子进程的值,一个是返回到父进程的值
*问题:这个函数是父进程执行的,pid不应该是fork返回到父进程的值么,为什么可能为0呢???
*请各位指教。
****************************************************************************************/
printf("Current time:%d\n",pid);
kill(pid,SIGUSR1);
}

int main(){;
int i;
int stat;
signal(SIGCLD,SIG_IGN);
signal(SIGUSR1,SIG_IGN);
signal(SIGUSR2,handle);
pid=fork();
if(pid<0){
perror("fork");
exit(-1);
}
else if(pid==0){
kill(getppid(),SIGUSR2);
pause();
exit(0);
}
wait(&stat);
return 0;
}
...全文
97 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaowai0219 2010-04-18
  • 打赏
  • 举报
回复
问题应该出在写时复制(Copy-On-Write)上,引用一段关于写时复制的描述:
现在的Unix内核(包括Linux),采用一种更为有效的方法称之为写时复制(或COW)。这种思想相当简单:父进程和子进程共享页面而不是复制页面。然而,只要页面被共享,它们就不能被修改。无论父进程和子进程何时试图写一个共享的页面,就产生一个错误,这时内核就把这个页复制到一个新的页面中并标记为可写。原来的页面仍然是写保护的:当其它进程试图写入时,内核检查写进程是否是这个页面的唯一属主;如果是,它把这个页面标记为对这个进程是可写的。
当fork()调用后,父进程和子进程共享地址空间(此时数据段的pid,ppid都为0),其后不管是父进程先返回还是子进程先返回,都要修改pid的值,就会发生缺页错误,内核将复制页面。你的程序的问题就出在这儿,在这个时间段执行kill(pid,SIGUSR1),pid的值就会是0(就是数据段的初始值)。
sabflying 2010-04-17
  • 打赏
  • 举报
回复
不应该把pid定义为全局变量
elated 2010-04-16
  • 打赏
  • 举报
回复
fork返回两次
maixl 2010-04-15
  • 打赏
  • 举报
回复
写错了,是这样

else if((pid ==0){
g_tmpPid = pid;
kill(getppid(),SIGUSR2);
pause();
exit(0);
}

maixl 2010-04-15
  • 打赏
  • 举报
回复
是不返回两次,试验一下就知道了

在定义一个全局变量g_tmpPid;

else if((g_tmpPid = pid)==0){
kill(getppid(),SIGUSR2);
pause();
exit(0);
}

static void handle(int signo){
printf("Current time:%d\n",g_tmpPid);
kill(pid,SIGUSR1);
}


看还是不是打印两种可能,这时候打印都是0了。
xiaowai0219 2010-04-15
  • 打赏
  • 举报
回复
可能如3楼所说,fork只返回一次值。我也觉得调用一次函数之返回一次值比较靠谱。只是看到的书上都是说返回两次的(尽信书不如无书),可能是为了让读者更容易理解吧。。。 不管怎样,父,子进程中的pid的值不同是事实。并且,不论是哪种说法,对编程也没多大影响也应该是事实吧

似乎都还没有人对Linux IPC提供建议哦
xiaowai0219 2010-04-15
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 chuaimeng 的回复:]
1. 不与实际的项目相结合,只是单纯地从书本上抄些例子, 是很难掌握其要领的。
[/Quote]
我也并不只是照着例子敲,一般都会跟踪看它怎么运行的,然后自己有想法也加进去
[Quote=引用 3 楼 chuaimeng 的回复:]
应该是只会出现0,而不会出现子进程的pid才对。如果运行结果确实如LZ所说,那可能就与操作系统的机制有关了。
子进程被创建后,它会复制一份与父进程相同的代码。所以,在子进程中pid的值是0;而在父进程中pid的值是子进程的进程ID。也就是pid在两个进程中分别被初始化的值。
[/Quote]
结果我试了很多遍了,确实两个都有可能,因此也在怀疑是操作系统的问题(用的是ubuntu 9.04)。
那个函数是子进程给父进程发送消息后,父进程去执行的,pid应该是子进程的进程ID吧。
maixl 2010-04-15
  • 打赏
  • 举报
回复
fork是调用一次,两次返回,pid你定义成全局,可有可能是子进程pid或0

[Quote=引用 3 楼 chuaimeng 的回复:]
1. 不与实际的项目相结合,只是单纯地从书本上抄些例子, 是很难掌握其要领的。
2.

引用楼主 xiaowai0219 的回复:
多执行几次pid会出现不同的结果0,或者子进程的pid


这个请LZ再仔细检查一下程序运行结果,应该是只会出现0,而不会出现子进程的pid才对。如果运行结果确实如LZ所说,那可能就与操作系统的机制有关了。
子进程被创建后,它会复制一份与父进程相同的代……
[/Quote]
激情的头发 2010-04-15
  • 打赏
  • 举报
回复
1. 不与实际的项目相结合,只是单纯地从书本上抄些例子, 是很难掌握其要领的。
2.
[Quote=引用楼主 xiaowai0219 的回复:]
多执行几次pid会出现不同的结果0,或者子进程的pid
[/Quote]

这个请LZ再仔细检查一下程序运行结果,应该是只会出现0,而不会出现子进程的pid才对。如果运行结果确实如LZ所说,那可能就与操作系统的机制有关了。
子进程被创建后,它会复制一份与父进程相同的代码。所以,在子进程中pid的值是0;而在父进程中pid的值是子进程的进程ID。也就是pid在两个进程中分别被初始化的值。

3.
[Quote=引用楼主 xiaowai0219 的回复:]
一个是fork返回到子进程的值,一个是返回到父进程的值
[/Quote]
任何一个函数不可能返回两次,fork()同样也只返回一次。代码是这样执行的:
父进程调用fork()创建一个新的进程
fork()向父进程返回新创建进程的进程ID(假设创建成功)
父进程与子进程分别独立地运行

新创建的子进程从pid被赋值开始执行,而不是从执行fork()开始 。fork()是一个函数的地址,而pid是另一种类型的数据,编译器对这个赋值进行了一些转化(具体机制我不太清楚,但肯定是存在的),使得pid被赋值为0。
Wind_Runner 2010-04-15
  • 打赏
  • 举报
回复
是父子进程都用同一个信号处理程序引起的
xiaowai0219 2010-04-15
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 maixl 的回复:]
写错了,是这样

else if((pid ==0){
g_tmpPid = pid;
kill(getppid(),SIGUSR2);
pause();
exit(0);
}

[/Quote]
谢谢了哈,但是我贴这个出来不是为了简单的解决这个问题。而是想知道为什么会是这样的
steptodream 2010-04-15
  • 打赏
  • 举报
回复

那就加油吧!

23,125

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧