2011-11-02 44 views
12

Tôi muốn tăng giá trị macro FD_SETSIZE cho hệ thống của mình. Có cách nào để tăng FD_SETSIZE để chọn không thất bạiTăng giới hạn FD_SETSIZE và chọn

+0

có, Trong trường hợp của tôi, tôi cần khoảng 2048. Có cách nào để đặt nó không? –

+0

vì tôi muốn tăng giới hạn máy chủ của mình để hỗ trợ nhiều kết nối. –

+2

Không có hành vi phạm tội, nhưng suy nghĩ về việc tăng 'FD_SETSIZE' là một điều khá câm để làm. 2048 kết nối đồng thời (hay đúng hơn, nhiều hơn thế) nằm trong phạm vi mà 'epoll_wait' vượt trội hơn cả' select' và 'poll' đơn giản vì nó không cần copy 8 kilobyte dữ liệu mỗi lần và không cần để lặp lại hơn hai nghìn bộ mô tả mỗi lần. – Damon

Trả lời

8

Theo tiêu chuẩn, không có cách nào để tăng FD_SETSIZE. Một số chương trình và thư viện (không thích hợp) cố gắng giải quyết vấn đề này bằng cách phân bổ không gian bổ sung cho đối tượng fd_set và chuyển các giá trị lớn hơn FD_SETSIZE tới các macro FD_*, nhưng đây là một ý tưởng rất tồi vì việc triển khai mạnh mẽ có thể thực hiện kiểm tra giới hạn đối số và hủy bỏ nếu nó nằm ngoài phạm vi.

Tôi có giải pháp thay thế luôn hoạt động (mặc dù không bắt buộc theo tiêu chuẩn). Thay vì một đối tượng fd_set đơn lẻ, hãy phân bổ một mảng lớn đủ để giữ fd tối đa bạn cần, sau đó sử dụng FD_SET(fd%FD_SETSIZE, &fds_array[fd/FD_SETSIZE]) v.v. để truy cập tập hợp.

+0

Tôi đang sử dụng thư viện của bên thứ ba. Có cách nào dễ dàng để vá mã với đề xuất của bạn hoặc thay thế bằng hồ bơi? –

+3

đây là câu trả lời sai. vui lòng đọc http://support.microsoft.com/kb/111855 – dns

+5

@dns: Đó là tài liệu giả. :-) Vui lòng đọc http://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html. OK, nói đùa sang một bên, hãy giải thích những gì bạn nghĩ là "sai" về câu trả lời của tôi. –

12

Tôi cũng khuyên bạn nên sử dụng poll nếu có thể. Và tồn tại một số thư viện xử lý "sự kiện" như libevent hoặc libev (hoặc khả năng sự kiện của Glib từ GTK hoặc QtCore, v.v.) sẽ giúp bạn. Ngoài ra còn có những thứ như epoll. Và sự cố của bạn có liên quan đến C10k

+1

có. tôi nghĩ đây là câu trả lời tối thượng. Nếu một trong các bộ giám sát của bạn theo dõi rơi trên 1024 dưới Linux, hoặc là bạn phải HACK thông qua cấu trúc fd_set (và rủi ro hơn nữa vấn đề anyway), hoặc sử dụng thăm dò những gì là ... tốt hơn. –

1

thực sự có IS một cách để tăng FD_SETSIZE trên cửa sổ. định nghĩa của nó trong winsock.h và mỗi microsoft bản thân bạn có thể tăng nó bằng cách đơn giản định nghĩa nó TRƯỚC KHI bạn bao gồm winsock.h

http://support.microsoft.com/kb/111855

tôi làm điều đó tất cả các thời gian và đã không có vấn đề giá trị lớn nhất tôi đã sử dụng là khoảng 5000 cho một máy chủ tôi đã phát triển

+4

BSD và Windows cho phép đặt FD_SETSIZE. Không phải Linux, trong đó kích thước nội bộ fd_set được thiết lập bởi __FD_SETSIZE được mã hóa thành 1024. Đối với Linux, tốt hơn nên sử dụng thăm dò vì slecet không thể làm việc nhiều hơn 1024 ký tự đầu tiên. trong thực tế nó có thể xuất hiện để làm việc trên Linux nhưng sẽ sử dụng bit bên ngoài phân bổ fd_set, những gì chắc chắn sẽ làm hỏng stack và gây ra sự cố. Đó là lý do tại sao câu trả lời hiện tại là phân bổ cho chính mình nhiều vị trí hơn trên chồng những gì không phải là rất đẹp. –

+1

Các câu hỏi giao dịch với Linux, không phải cửa sổ. – mpromonet

8

Sẽ tốt hơn (và dễ dàng) để thay thế bằng cuộc thăm dò ý kiến. Nói chung cuộc thăm dò() là một đơn giản thay thế thả-in cho chọn() và không giới hạn bởi 1024 của FD_SETSIZE ...

fd_set fd_read; 
int id = 42; 
FD_ZERO(fd_read); 
FD_SET(id, &fd_read); 
struct timeval tv; 
tv.tv_sec = 5; 
tv.tv_usec = 0; 
if (select(id + 1, &fd_read, NULL, NULL, &tv) != 1) { 
    // Error. 
} 

trở thành:

struct pollfd pfd_read; 
int id = 42; 
int timeout = 5000; 
pfd_read.fd = id; 
pfd_read.events = POLLIN; 
if (poll(&pfd_read, 1, timeout) != 1) { 
    // Error 
} 

Bạn cần phải bao gồm thăm dò. h cho cấu trúc pollfd.

Nếu bạn cần viết cũng như đọc thì hãy đặt cờ sự kiện là POLLIN | POLLOUT.

6

Có thể tăng FD_SETSIZE vượt quá __FD_SETSIZE (được xác định trong sys/types.h) trước khi bao gồm sys/select.h.

Căn cứ như thế chúng ta có thể thiết lập FD_SETSIZE để 2048:

#include <sys/types.h> 
#undef __FD_SETSIZE 
#define __FD_SETSIZE 2048 
#include <sys/select.h> 
#include <stdio.h> 

int main() 
{ 
    printf("FD_SETSIZE:%d sizeof(fd_set):%d\n",FD_SETSIZE,sizeof(fd_set)); 
    return 0; 
} 

sẽ in:

FD_SETSIZE: 2048 sizeof (fd_set): 128

Tuy nhiên nếu FD_SETSIZE là sau giá trị được sửa đổi, sizeof (fd_set) phải là 256 (2048/8) và không phải là 128 (1024/8). Điều này là do bao gồm sys/types.h đã xác định fd_set với 1024.


Để sử dụng một fd_set lớn hơn, nó có thể định nghĩa là một mở rộng như thế này:

#include <sys/select.h> 
#include <stdio.h> 

#define EXT_FD_SETSIZE 2048 
typedef struct 
{ 
    long __fds_bits[EXT_FD_SETSIZE/8/sizeof(long)]; 
} ext_fd_set; 

int main() 
{ 
    ext_fd_set fd; 
    int s; 
    printf("FD_SETSIZE:%d sizeof(fd):%ld\n", EXT_FD_SETSIZE, sizeof(fd)); 
    FD_ZERO(&fd); 
    while (((s=dup(0)) != -1) && (s < EXT_FD_SETSIZE)) 
    { 
     FD_SET(s, &fd); 
    } 
    printf("select:%d\n", select(EXT_FD_SETSIZE,(fd_set*)&fd, NULL, NULL, NULL)); 
    return 0; 
} 

in này:

FD_SETSIZE: 2048 sizeof (fd): 256

chọn: 2045


Để mở hơn 1024 trình biên tập, cần tăng giới hạn sử dụng ví dụ ulimit -n 2048.

+1

Đây là câu trả lời đúng. –

+1

Điều này có khả năng gây nguy hiểm. Nếu không tham gia vào vấn đề tuân thủ các tiêu chuẩn (hợp lệ, IMO), có một trường hợp sử dụng rõ ràng hơn, điều này có thể thất bại, và đó là khi liên kết với một thư viện được biên dịch để sử dụng FD_SETSIZE do hệ thống xác định. Sử dụng 'poll()' là cách tiếp cận đúng. – edam

Các vấn đề liên quan