每個人都知道進程監聽套接字上的連接的經典模型,並分派一個新進程來處理每個新連接。通常的做法是讓父進程立即在新創建的套接字上調用close
,遞減句柄計數以便只有子對象具有新套接字的句柄。在Linux中創建新線程是否重複文件描述符和套接字描述符?
我讀過唯一的區別 Linux中的進程和線程之間是線程共享相同的內存。在這種情況下,我假設產生一個新的線程來處理一個新的連接也複製文件描述符,並且還需要'父'線程關閉它的套接字的副本?
每個人都知道進程監聽套接字上的連接的經典模型,並分派一個新進程來處理每個新連接。通常的做法是讓父進程立即在新創建的套接字上調用close
,遞減句柄計數以便只有子對象具有新套接字的句柄。在Linux中創建新線程是否重複文件描述符和套接字描述符?
我讀過唯一的區別 Linux中的進程和線程之間是線程共享相同的內存。在這種情況下,我假設產生一個新的線程來處理一個新的連接也複製文件描述符,並且還需要'父'線程關閉它的套接字的副本?
編號線程共享相同的內存,因此它們共享相同的變量。如果關閉父線程中的套接字,它也將在子線程中關閉。
編輯:
人叉:孩子繼承複製打開文件描述符的父母的一套。
人並行線程:線程份額一系列其他的屬性(即,這些屬性是進程範圍,而不是每個線程):[...]打開文件描述符
有些代碼:
#include <cstring>
#include <iostream>
using namespace std;
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <unistd.h>
// global variable
int fd = -1;
void * threadProc(void * param) {
cout << "thread: begin" << endl;
sleep(2);
int rc = close(fd);
if (rc == -1) {
int errsv = errno;
cout << "thread: close() failed: " << strerror(errsv) << endl;
}
else {
cout << "thread: file is closed" << endl;
}
cout << "thread: end" << endl;
}
int main() {
int rc = open("/etc/passwd", O_RDONLY);
fd = rc;
pthread_t threadId;
rc = pthread_create(&threadId, NULL, &threadProc, NULL);
sleep(1);
rc = close(fd);
if (rc == -1) {
int errsv = errno;
cout << "main: close() failed: " << strerror(errsv) << endl;
return 0;
}
else {
cout << "main: file is closed" << endl;
}
sleep(2);
}
輸出是:
thread: begin
main: file is closed
thread: close() failed: Bad file descriptor
thread: end
你有參考嗎? – 2009-10-05 20:05:17
我在這裏工作時沒有和我在一起,但是一旦我回家,我可以查看Stevens'UNPv2的副本。 – 2009-10-05 20:09:33
@Shelby - 謝謝,我有一份UNP,但只讀了三分之一。 – 2009-10-05 20:18:49
在Linux線程通過使用CLONE_FILES標誌clone系統調用來實現:
如果CLONE_FILES設置,主叫 進程和子進程共享 相同的文件描述符表。由調用 進程或子進程創建的任何 文件描述符也是 在其他進程中也是有效的。 同樣,如果其中一個進程 關閉了文件描述符,或者更改了其關聯的標誌(使用 fcntl(2)F_SETFD操作),其他 進程也受到影響。
而且看看對細節的glibc的源代碼,它是如何在createthread.c使用:
int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL
| CLONE_SETTLS | CLONE_PARENT_SETTID
| CLONE_CHILD_CLEARTID | CLONE_SYSVSEM
#if __ASSUME_NO_CLONE_DETACHED == 0
| CLONE_DETACHED
#endif
| 0);
原則上,Linux的克隆()不僅可以實現一個新的進程(如叉()),或者一個新的線程(也許像pthread_create),但也包括其中的任何東西。
實際上,它只能用於其中之一。使用pthread_create創建的線程與進程中的所有其他線程共享文件描述符(而不僅僅是父級)。這是不可談判的。
共享文件描述符並擁有一個副本是不同的。如果您有副本(如fork()),則在文件句柄消失之前,必須關閉所有副本。如果你在一個線程中共享FD,一旦關閉它,它就消失了。
「我讀過Linux中進程和線程之間唯一的區別是線程共享相同的內存。」進程和線程之間還有很多其他差異。例如,進程可以包含多個線程。 – 2017-01-03 15:52:59