大部分这种问题都能够解决,在文章的最后,提到了一种特殊情况,就是父子进程中的端口占用情况。父进程监听一个端口后,fork出一个子进程,然后kill掉父进程,再重启父进程,这个时候提示端口占用,用netstat查看,子进程占用了父进程监听的端口。

原理其实很简单,子进程在fork出来的时候,使用了写时复制(COW,Copy-On-Write)方式获得父进程的数据空间、 堆和栈副本,这其中也包括文件描述符。刚刚fork成功时,父子进程中相同的文件描述符指向系统文件表中的同一项(这也意味着他们共享同一文件偏移量)。这其中当然也包含父进程创建的socket。

接着,一般我们会调用exec执行另一个程序,此时会用全新的程序替换子进程的正文,数据,堆和栈等。此时保存文件描述符的变量当然也不存在了,我们就无法关闭无用的文件描述符了。所以通常我们会fork子进程后在子进程中直接执行close关掉无用的文件描述符,然后再执行exec。

但是在复杂系统中,有时我们fork子进程时已经不知道打开了多少个文件描述符(包括socket句柄等),这此时进行逐一清理确实有很大难度。我们期望的是能在fork子进程前打开某个文件句柄时就指定好:“这个句柄我在fork子进程后执行exec时就关闭”。其实时有这样的方法的:即所谓 的 close-on-exec。

回到我们的应用场景中来,只要我们在创建socket的时候加上SOCK_CLOEXEC标志,就能够达到我们要求的效果,在fork子进程中执行exec的时候,会清理掉父进程创建的socket。

#ifdef WIN32SOCKET ss = ::socket(PF_INET, SOCK_STREAM, 0);
#elseSOCKET ss = ::socket(PF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
#endif

当然,其他的文件描述符也有类似的功能,例如文件,可以在打开的时候使用O_CLOEXEC标识(linux 2.6.23才开始支持此标记),达到和上面一样的效果。或者使用系统的fcntl函数设置FD_CLOEXEC即可。

//方案A
int fd = open(“foo.txt”,O_RDONLY);
int flags = fcntl(fd, F_GETFD);
flags |= FD_CLOEXEC;
fcntl(fd, F_SETFD, flags);
//方案B,linux 2.6.23后支持
int fd = open(“foo.txt”,O_RDONLY | O_CLOEXEC);

好了,现在我们终于可以完美的解决端口占用这个令人烦恼的问题了。

linux 进程间 close-on-exec 机制 简介相关推荐

  1. linux共享内存示例,linux 进程间共享内存示例

    写入端: #include #include #include #include #include using namespace std; struct MappingDataType { int ...

  2. msgget();msgsnd();msgrcv();msgctl(); 消息队列 Linux进程间的通信方式之消息队列

    Linux进程间的通信方式 ----消息队列. 消息队列和共享内存类似 消息队列它允许一个或多个进程向它写消息,一个或多个进程向它写读消息. 消息队列存在于系统内核中,消息的数量受系统限制. 我们来看 ...

  3. 深刻理解 Linux 进程间七大通信(IPC)

    前言 网络编程是 Linux C/C++的面试重点,今天我就来聊一聊进程间通信的问题,文章末尾列出了参考资料,希望帮助到大家. 篇幅有点长,希望大家耐心阅读. Linux 下的进程通信手段基本上是从 ...

  4. Linux 进程间通讯(IPC)方式 ------- 共享内存

    Linux 进程间通讯(IPC)方式有以下几种: 1->管道(pipe)和有名管道(fifo). 2->消息队列 3->共享内存 4->信号量 5->信号(signal) ...

  5. Linux 进程间通讯方式 pipe()函数

    Linux 进程间通讯方式有以下几种: 1->管道(pipe)和有名管道(fifo). 2->消息队列 3->共享内存 4->信号量 5->信号(signal) 6-&g ...

  6. linux进程间信号量

    linux进程间信号量 Linux 提供的各种系统调用来实现一个具有两种状态的信号量(binary semaphore). 分配和释放 和用于分配.释放共享内存的 shmget 和 shmctl 类似 ...

  7. linux无名管道实验代码,Linux 进程间通讯之创建无名管道和读写无名管道

    Linux进程间通讯的方式: 1. 管道(pipe)和有名管道(FIFO). 2. 信号(signal) 3. 消息队列 4. 共享内存 5. 信号量 6. 套接字(socket) 管道通讯: 无名管 ...

  8. linux进程间通讯-信号

    文章目录 进程间通信功能 信号 信号的概念 产生信号的方式 信号的默认(缺省)处理方式 进程接收到信号后的处理方式 kill函数 alarm函数 raise函数 abort函数 pause函数 sig ...

  9. Linux进程间通讯

    最初Unix IPC包括:管道.FIFO.信号: System V IPC包括:System V消息队列.System V信号灯.System V共享内存区: Posix IPC包括: Posix消息 ...

  10. Linux进程间通讯之消息队列

    首先有个大体的概念:http://www.xefan.com/archives/83703.html 头文件: #include <sys/ipc.h> #include <sys/ ...

最新文章

  1. 数据结构与算法之KMP算法02
  2. boost::allocate_shared_noinit相关的测试程序
  3. Git 在推送(Push)信息的时候提示git did not exit cleanly (exit code 1)的解决办法
  4. 使用 C# 代码实现拓扑排序
  5. 849. 到最近的人的最大距离
  6. 先学python还是ros_ROS入门学习
  7. htmlselect保留上次选择内容_搬家买什么工具,搬家有什么技巧,搬家选择什么公司?...
  8. OpenCV-图像锐化
  9. C语言之选择结构与循环结构
  10. c语言图书信息管理系实验心得,C语言图书信息管理系统实验报告.doc
  11. 简单c语言程序例子与运行结果图,C语言程序第一次作业
  12. 浅谈防勒索病毒方案之主机加固
  13. 电脑计算机硬盘内存满了怎么清理,电脑磁盘空间怎么清理 电脑磁盘空间清理方法【详解】...
  14. 算法学习之贪心法(会议安排)
  15. c语言互质欧拉函数,互质与欧拉函数
  16. 攀藤 5003粉尘激光传感器arduino使用
  17. SQL Server中的日期和时间:DATEADD()
  18. 洛谷入门1【顺序结构】题单题解
  19. host管理工具SwitchHosts的使用
  20. Servlert 下 (HttpServletRequest 类和 HttpServletResponse 类)

热门文章

  1. python中分支结构与c语言中有何区别_C语言的分支语句有哪几种?C语言分支结构的基本形式是什么,区别是什么?...
  2. 互联网协议 — L2TP 二层隧道协议
  3. IPython4_Notebook
  4. STM32堆栈大小及位置
  5. C语言基础学习day10
  6. 用按位异或运算符交换两个数,不引入第三个变量
  7. 原生js实现preAll和nextAll方法
  8. [编程题]字符串最后一个单词的长度
  9. 【2781】二分练习 sdutOJ
  10. C# typeof Gettype is as 拆箱 装箱