被linux线程基础折磨的点滴——还是没得到完美的答案,但至少得到了所需
#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main(void)
{ printf("origin is %d\n",getpid());
printf("origin p is %d\n",getppid()); pid_t pid;
pid=fork();
if(pid>)
{
printf("parent is %d\n",getpid());
}
else if(pid==)
{ printf("child is %d\n",getpid());
printf("child's parent is %d\n",getppid());
}
}
输出:

很奇怪,为什么在子进程中调用父进程的PID会是1224,而parent明明是3973啊,有点晕。
为了追踪代码进程,我在上述代码最后加了一个while(1)循环,不加还好,加了之后更晕了。
#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main(void)
{ printf("origin is %d\n",getpid());
printf("origin p is %d\n",getppid()); pid_t pid;
pid=fork();
if(pid>)
{
printf("parent is %d\n",getpid());
}
else if(pid==)
{ printf("child is %d\n",getpid());
printf("child's parent is %d\n",getppid());
}
while()
;
}
输出:

啊,为什么又对了啊,加了一个循环阻塞之后,子进程中调用父进程的PID显示和parent一样了。
这是为什么啊,各种资料论坛求助,得到一个回答:


突然就觉得我理真理不远了,如果父进程结束,子进程再调用父进程PID确实是会有问题啊,知道这个之后,测试了,在parent的printf之后加wait或者pause函数,确实显示就正确。但是程序员血液刺激着我,就算父进程先销毁了(到底子进程还是父进程先销毁还得看操作系统的调度实现,就是不确定的意思?),那我在子进程中调用getppid函数得到的值为什么每次运行都一样啊,依照经验来看调用销毁了的东西应该会出现随机值的呀,看来这里还有学问。继续摸爬滚打,得到资料:
在Linux中父进程先于子进程退出会造成子进程成为孤儿进程,而每当系统发现一个孤儿进程时,就会自
动由1号进程(init)收养它,这样,原先的子进程就会变成init进程的子进程。
这也就为什么每次在子进程中调用父进程都是显示1224,查看PID号,确实为1号进程(init)。这至少证明
了,引起这个现象的原因,确实为父进程被销毁了(这是不是意味着在本就复杂的多进程程序中要考虑的事情更多了呢)。 貌似,我终于可以放下这个问题继续学习了,但是,程序员有时几句简单程序,可能会带来意想不到的结果。
我们总是不安寂寞,我也不知道为什么,就想加了个语句再试试,在main函数后面加个scanf阻塞一下,同时
去除最后的while循环,
#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main(void)
{ printf("origin is %d\n",getpid());
printf("origin p is %d\n",getppid());
int a;
printf("input a is....\n");
scanf("%d",&a);
pid_t pid;
pid=fork();
if(pid>)
{
printf("parent is %d\n",getpid());
}
else if(pid==)
{ printf("child is %d\n",getpid());
printf("child's parent is %d\n",getppid());
}
}

运行结果显示,子进程正确打印了了父进程的PID,这下是彻底晕了,难道忙活这么久,查阅这么多资料
之后,发现还是不对?如上述代码,没有阻塞父进程的销毁,按理说它应该被销毁,子进程中应该打印parent
为1224才对,为什么这个时候父进程就不被销毁了呢?实在没明白操作系统干了什么,毕竟自己不是写
操作系统的人,有些东西了解即可。最后只能在一个用户层面得到一个总结:
测试现象表明,确实存在父进程销毁使子进程被init收养;
但是除了阻塞父进程的销毁(while循环或者pause函数等)之外,子进程还是可以得到父进程的ID,
例如加了一个scanf,就这么一个scanf,让子进程得以访问父进程ID,也证明父进程没被销毁,那么问题来了,
到底是什么原因呢,按理说就算前面有个阻塞,父进程也应该被销毁的,但事实上linux并没有,
我并不清楚linux在这里的实现细节,只能在用户层面测试得到,只要你阻塞过父进程,他将存在,可以
通过子进程访问。 如果有人知道原因,请留言告诉我,不胜感激!这个问题,只能先到这了。。。 拨开云雾:就在加了scanf之后,又测试了一把,我在想为什么系统会保留父进程,是不是因为我输入
的数字a没有被使用的原因,于是,在上面代码仅仅增加一句,终于,我的猜想是正确的,使用一下a测试:
if(pid>)
{
a++;
printf("parent is %d\n",getpid());
}
使用了a之后,输出结果:
终于,如我所期了,父进程销毁,这样来理解linux系统的实现是可以接受的,操作系统认为你输入了
数据,但还没去使用它,所以保留你的进程,如果你使用了那个变量之后,操作系统将其进程销毁。这个
和输入缓冲区到内核实现有关系,至于底层到底是怎么的,我也就不关心了,但至少要了解到这个层面。自此,终于可以继续向下学习了^_^
被linux线程基础折磨的点滴——还是没得到完美的答案,但至少得到了所需的更多相关文章
- linux 线程基础
线程基础函数 查看进程中有多少个线程,查看线程的LWP ps -Lf 进程ID(pid) 执行结果:LWP列 y:~$ ps -Lf 1887 UID PID PPID LWP C NLWP STIM ...
- Linux线程基础
复习中掌握线程的基本管理即可,而不用考虑线程的同步: 创建线程花费的代价,比创建进程小得多,所以同一个进程的,多个线程执行多个任务-->比多个进程执行多个任务更有效率. 线程也分为用户级线程.内 ...
- Linux线程基础函数
1. 线程标识: (1) 比较两个线程ID: #include <pthread.h> int pthread_equal(pthread_t tid1, pthread_t tid2); ...
- Linux 系统应用编程——线程基础
传统多任务操作系统中一个可以独立调度的任务(或称之为顺序执行流)是一个进程.每个程序加载到内存后只可以唯一地对应创建一个顺序执行流,即传统意义的进程.每个进程的全部系统资源是私有的,如虚拟地址空间,文 ...
- [转载]Linux 线程实现机制分析
本文转自http://www.ibm.com/developerworks/cn/linux/kernel/l-thread/ 支持原创.尊重原创,分享知识! 自从多线程编程的概念出现在 Linux ...
- Linux进程基础
Linux进程基础 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 计算机实际上可以做的事情实质上非常简单,比如计算两个数的和 ...
- Linux线程学习(二)
线程基础 进程 系统中程序执行和资源分配的基本单位 每个进程有自己的数据段.代码段和堆栈段 在进行切换时需要有比较复杂的上下文切换 线程 减少处理机的空转时间,支持多处理器以及减少上下文切换开销, ...
- Linux 线程与进程,以及通信
http://blog.chinaunix.net/uid-25324849-id-3110075.html 部分转自:http://blog.chinaunix.net/uid-20620288-i ...
- Qt之线程基础
何为线程 线程与并行处理任务息息相关,就像进程一样.那么,线程与进程有什么区别呢?当你在电子表格上进行数据计算的时候,在相同的桌面上可能有一个播放器正在播放你最喜欢的歌曲.这是一个两个进程并行工作的例 ...
随机推荐
- map函数原理
# -*- coding: utf-8 -*- #python 27 #xiaodeng #map函数 #map函数会对一个序列对象中的每一个元素应用被传入的函数,并返回一个包含了所有函数调用结果的一 ...
- JavaScript的技巧和最佳实践
JavaScript是一个绝冠全球的编程语言,可用于Web开发.移动应用开发(PhoneGap.Appcelerator).服务器端开发 (Node.js和Wakanda)等等.JavaScript还 ...
- PHP-学习大规模高并发Web系统架构及开发推荐书籍
以下书籍内容涵盖大型网站开发中几个关键点:高可用.高性能.分布式.易扩展.如果想对大规模高并发Web系统架构及开发有很系统的学习,可以阅读以下书籍,欢迎补充! 一.<Linux企业集群—用商用硬 ...
- 简单安装MongoDB
前言 首先说明一下环境,以免环境的不同造成不必要的影响 本次采用centos6.8版本linux系统 [root@dev1 ~]# cat /etc/redhat-release CentOS rel ...
- java.lang.UnsupportedClassVersionError: org/hibernate/SessionFactory : Unsupported major.minor version 52.0
问题: 在学习hibernate的过程中,涉及导入jar包的问题,写该文的时候是从官网下载的最新的hibernate的jar包hibernate-release-5.2.10.Final .在测试时, ...
- linux 浏览查看文件more,less,head,tail,cat,tac,od,nl命令使用简介
参考:linux 基本命令详解 cat,tac,nl,more,less,head,tail,od 命令more,less,head,tail,cat,tac,od,nl等是是使用Linux系统常用的 ...
- NSURLRequestCachePolicy 缓存策略
1> NSURLRequestUseProtocolCachePolicy = 0, 默认的缓存策略, 如果缓存不存在,直接从服务端获取.如果缓存存在,会根据response中的Cache-Co ...
- 1.Java基础-面向对象编程思想(封装继承多态接口)
封装: 1.定义:隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别. 2.封装的目的是:增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口,一特定的 ...
- 转 web前端性能分析--实践篇
当我们知道了web前端性能的关键点后,那么接下来要做的就是如何去具体实施并获取这些关键点的数据了.通过前面的学习知道了不少好的工具,经过对比后个人觉得dynatrace还是不错的. 不仅支持ie,ff ...
- PLSQL_性能优化索引Index介绍(概念)
2014-06-01 BaoXinjian