我有一个有很多线程的程序。有些线程是TCP服务器......每个服务器都会触发新线程来处理任何新连接。
在一个处理单个客户端的线程中,我调用fork()。子进程调用setpgid()(创建一个新组),然后调用system()(C / C ++标准库的函数)。父进程不断进行小睡(usleep()函数)并检查时间限制。如果在子进程从system()返回之前超过了时间限制,则父SIGKILL表示子进程。
我正在使用:Linux(Ubuntu),pthreads等。只有C / C ++标准库!
我的问题:子进程上的所有线程和TCP套接字会发生什么?这些东西是从父进程继承的吗?子和父是否同时运行所有这些线程和TCP服务器?对我来说没有任何意义......当父母SIGKILLs生孩子时,套接字是否只能在孩子内部或父母内部关闭?
目前,我实际上使用exec()来清理子进程的整个映像,但是如果它安全的话,我宁愿直接调用system()。
答案 0 :(得分:3)
TCP套接字等文件描述符(a.k.a. fds)通过fork继承。它们后面的文件或设备通常保持打开和可维护状态,直到它的最后一个文件描述符在进程终止时关闭或解除。因此,SIGKILL的子节点不会影响与父节点共享的TCP套接字。
然而,只有fork()线程在子进程中执行。不复制其他控制线程。你的情况看起来像这样:
+-- PID 100 -------------+ # parent
| fds: 0, 1, 2, 3 ... N | # fds: stdin, stdout, stderr, socket ... socket
| threads: |
| 0 (main) |
| 1 (tcp server) |
| 2 (forky) ---------(fork(2))-+
| ... | |
| N (tcp server) | |
+------------------------+ |
|
|
+-- PID 101 -------------+ # child
| fds: 0, 1, 2, 3 ... N | # fds: inherited
| threads: |
| 0 (copy of forky) | # will exec() ?
+------------------------+
调用exec
将用一些文本main()
替换PID 101过程映像(并关闭标记为FD_CLOEXEC的任何文件描述符)。相反,调用system("whatever")
可能会产生至少两个进程:一个(大)子/bin/sh
和一个(伟大的)孙子“无论如何”。
混淆线程,分支和共享资源很容易混淆自己,特别是如果将旧的旧接口(例如system()
)混合在一起。慢慢来,明确地丢弃不需要的资源,并一次解决一件事。