linux进程那些事 ---- 进程基础知识杂谈

下文整理了linux进程相关的知识点,都比较实用。各个知识点可能没什么相关性,跳跃性比较强,所以我称之为“杂谈”。

1.如何在linux上启动一个daemon进程?如何停止一个daemon进程?为什么要fork两次?
1)linux平台上,我们应该fork父进程两次以启动一个后台服务进程。原因是为了保证daemon进程完全脱离terminal。为什么要脱离terminal呢?因为我们要避免daemon接收到发给terminal的信号例如关闭terminal时候的SIGHUP。
创建daemon的具体步骤如下:
a.父进程fork子进程;
b.父进程退出。子进程的父进程变成init。
c.子进程调用 setsid() 以启动一个新的没有terminal的session。这时子进程其实已经脱离了terminal,但还是有可能重新获得terminal,所以为了保险起见我们还需要再fork一次。调用setsid()的另一个目的是避免daemon进程收到发给进程组的信号,setsid()会把daemon放进一个新的进程组。
d.子进程fork一个新的子进程
e.子进程退出
f.新的子进程成为daemon进程。至此,这个daemon进程已经不可能关联到任何terminal。
具体细节请参考下面两篇文章
https://stackoverflow.com/questions/8777602/why-must-detach-from-tty-when-writing-a-linux-daemon
http://thelinuxjedi.blogspot.com/2014/02/why-use-double-fork-to-daemonize.html
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap11.html#tag_11_01_03
2)退出daemon进程的方法有很多,下面列举两个常用的方法。
a.通过某个信号量实现后台服务停止。后台进程可以起一个线程睡眠在该信号量上,用户可以通过一条命令修改信号量唤醒该线程,从而触发后台服务退出。
b.通过配置文件实现后台服务停止。后台服务可以设一个计时器不断检查该配置文件,然后根据配置决定是否退出。
2.linux进程间通信机制有哪些?

Linux进程通信机制及使用场景
进程通信机制特点使用场景
Domain socket与IPC消息机制Domain socket与IPC消息机制都可以用来在进程之间传递消息。如果单单传递比较短的控制消息的话,个人觉得两者没什么大区别,具体选用哪种方式看个人习惯适合进程间传递控制消息
信号量信号量可以用来保护共享资源,实现对共享资源的原子操作实现原子操作,保护共享资源
管道管道的本质是文件,一个进程在文件的一端写,另一个进程在文件的另一端读适合大量数据传输
共享内存共享内存的本质是将同一块物理内存映射到不同进程的地址空间,所以对共享内存的访问性能极高,但是共享内存不考虑冲突以及竞争的问题,所以可能需要和其他通信机制比如锁结合使用适合低延时场景,例如需要直接操作显存的场景
信号信号也是进程间常用的通信方式,但是信号经常被用于内核与进程通信,或者管理员通过系统命令管理进程的场景。在应用开发中以上列举的几种方式已经足够进程间通信,一般不需要使用信号实现进程间通信的目的。常用的信号有SIGKILL,SIGCHLD,SIGALRM,SIGINT内核与进程通信,或者管理员通过系统命令管理进程的场景
   

3.Linux进程的堆和栈
在x86平台下运行 cat /proc/[pid]/maps 我们可以看到每个进程的内存空间,其中栈空间是在高地址,堆空间是在低地址,有趣的是栈地址是从高地址向低地址生长,堆地址是从低地址向高地址生长,为什么会这样呢?首先,这是平台相关的,比如有的平台是反过来的,堆从高地址向低地址生长,栈从从低地址向高地址生长;其次,不管在什么平台堆和栈都是从内存的两头向中间生长,这么做的目的是为了有效地利用内存,如果不这么做的话堆和栈有可能会overlap。最后再提一个有趣的函数alloca,这个函数可以直接从栈里面分配内存,这样分配的内存就不需要释放,缺点是栈的size是有限的,如果分配的内存太大,栈会爆掉。具体参考下文:
https://stackoverflow.com/questions/4560720/why-does-the-stack-address-grow-towards-decreasing-memory-addresses
4.Linux的文件锁有Mandatory和Advisory两种模式,两种有何区别?使用场景是什么?
Advisory lock比较特别,linux并不会真正对被Advisory lock锁住的文件加锁。但只要相关的各个进程遵守Advisory lock,那么文件依然可以在这些进程之间被Advisory lock保护。不过,除了这些遵守Advisory lock以外的其他进程依然可以无视Advisory lock,随意访问和修改文件。所以,Advisory lock其实是一种进程间的“君子协议”,遵守这个协议的进程就能在锁的保护下访问文件。
Mandatory lock由内核强制执行,一旦文件被锁所有其他进程都不能访问,这种锁类似windows下的文件锁。但是这种锁可能导致很多非常难解决的竞争问题,所以出于设计考虑linux对Mandatory lock的支持很有限,并且这个feature很可能在未来的linux版本中被移除,更多细节参考下面两篇文章。另外Linux建议开发者使用Advisory lock,stackoverflow上也有人建议使用client-server模式实现对文件的访问控制。
https://www.kernel.org/doc/Documentation/filesystems/mandatory-locking.txt http://man7.org/linux/man-pages/man2/fcntl.2.html https://gavv.github.io/blog/file-locks/

5.linux的 longjmp 与 setjmp api
这两个api可以用来实现跨函数的跳转,类似c++的 try catch;不同之处在于longjmp 与 setjmp不确保栈的内容在跳转之后不发生变化,只有静态变量、全局变量在跳转之后是不变的。
6.父子进程的关系
如果父进程先退出,那么init成为子进程的父进程,但是这个行为根据不同的linux平台略有不同,具体参考:
The parent process ID of all of the existing child processes and zombie processes of the calling process shall be set to the process ID of an implementation-defined system process. That is, these processes shall be inherited by a special system process.
http://pubs.opengroup.org/onlinepubs/9699919799/functions/_Exit.html
如果子进程先退出,但是父进程又没有wait的话,这个子进程会变成僵尸进程;不过有趣的是,如果父进程稍后退出的话,这个僵尸进程会被回收。
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值