⑴ 关于linux下的select/epoll
select这个系统调用的原型如下
第一个参数nfds用来告诉内核 要扫描的socket fd的数量+1 ,select系统调用最大接收的数量是1024,但是如果每次都去扫描1024,实际上的数量并不多,则效率太低,这里可以指定需要扫描的数量。 最大数量为1024,如果需要修改这个数量,则需要重新编译Linux内核源码。
第2、3、4个参数分别是readfds、writefds、exceptfds,传递的参数应该是fd_set 类型的引用,内核会检测每个socket的fd, 如果没有读事件,就将对应的fd从第二个参数传入的fd_set中移除,如果没有写事件,就将对应的fd从第二个参数的fd_set中移除,如果没有异常事件,就将对应的fd从第三个参数的fd_set中移除 。这里我们应该 要将实际的readfds、writefds、exceptfds拷贝一份副本传进去,而不是传入原引用,因为如果传递的是原引用,某些socket可能就已经丢失 。
最后一个参数是等待时间, 传入0表示非阻塞,传入>0表示等待一定时间,传入NULL表示阻塞,直到等到某个socket就绪 。
FD_ZERO()这个函数将fd_set中的所有bit清0,一般用来进行初始化等。
FD_CLR()这个函数用来将bitmap(fd_set )中的某个bit清0,在客户端异常退出时就会用到这个函数,将fd从fd_set中删除。
FD_ISSET()用来判断某个bit是否被置1了,也就是判断某个fd是否在fd_set中。
FD_SET()这个函数用来将某个fd加入fd_set中,当客户端新加入连接时就会使用到这个函数。
epoll_create系统调用用来创建epfd,会在开辟一块内存空间(epoll的结构空间)。size为epoll上能关注的最大描述符数,不够会进行扩展,size只要>0就行,早期的设计size是固定大小,但是现在size参数没什么用,会自动扩展。
返回值是epfd,如果为-1则说明创建epoll对象失败 。
第一个参数epfd传入的就是epoll_create返回的epfd。
第二个参数传入对应操作的宏,包括 增删改(EPOLL_CTL_ADD、EPOLL_CTL_DEL、EPOLL_CTL_MOD) 。
第三个参数传入的是 需要增删改的socket的fd 。
第四个参数传入的是 需要操作的fd的哪些事件 ,具体的事件可以看后续。
返回值是一个int类型,如果为-1则说明操作失败 。
第一个参数是epfd,也就是epoll_create的返回值。
第二个参数是一个epoll_event类型的指针,也就是传入的是一个数组指针。 内核会将就绪的socket的事件拷贝到这个数组中,用户可以根据这个数组拿到事件和消息等 。
第三个参数是maxevents,传入的是 第二个参数的数组的容量 。
第四个参数是timeout, 如果设为-1一直阻塞直到有就绪数据为止,如果设为0立即返回,如果>0那么阻塞一段时间 。
返回值是一个int类型,也就是就绪的socket的事件的数量(内核拷贝给用户的events的元素的数量),通过这个数量可以进行遍历处理每个事件 。
一般需要传入 ev.data.fd 和 ev.events ,也就是fd和需要监控的fd的事件。事件如果需要传入多个,可以通过按位与来连接,比如需要监控读写事件,只需要像如下这样操作即可: ev.events=EPOLLIN | EPOLLOUT 。
LT(水平触发), 默认 的工作模式, 事件就绪后用户可以选择处理和不处理,如果用户不处理,内核会对这部分数据进行维护,那么下次调用epoll_wait()时仍旧会打包出来 。
ET(边缘触发),事件就绪之后, 用户必须进行处理 ,因为内核把事件打包出来之后就把对应的就绪事件给清掉了, 如果不处理那么就绪事件就没了 。ET可以减少epoll事件被重复触发的次数,效率比LT高。
如果需要设置为边缘触发只需要设置事件为类似 ev.events=EPOLLIN | EPOLLET 即可 。
select/poll/epoll是nio多路复用技术, 传统的bio无法实现C10K/C100K ,也就是无法满足1w/10w的并发量,在这么高的并发量下,在进行上下文切换就很容易将服务器的负载拉飞。
1.将fd_set从用户态拷贝到内核态
2.根据fd_set扫描内存中的socket的fd的状态,时间复杂度为O(n)
3.检查fd_set,如果有已经就绪的socket,就给对应的socket的fd打标记,那么就return 就绪socket的数量并唤醒当前线程,如果没有就绪的socket就继续阻塞当前线程直到有socket就绪才将当前线程唤醒。
4.如果想要获取当前已经就绪的socket列表,则还需要进行一次系统调用,使用O(n)的时间去扫描socket的fd列表,将已经打上标记的socket的fd返回。
CPU在同一个时刻只能执行一个程序,通过RR时间片轮转去切换执行各个程序。没有被挂起的进程(线程)则在工作队列中排队等待CPU的执行,将进程(线程)从工作队列中移除就是挂起,反映到Java层面的就是线程的阻塞。
什么是中断?当我们使用键盘、鼠标等IO设备的时候,会给主板一个电流信号,这个电流信号就给CPU一个中断信号,CPU执行完当前的指令便会保存现场,然后执行键盘/鼠标等设备的中断程序,让中断程序获取CPU的使用权,在中断程序后又将现场恢复,继续执行之前的进程。
如果第一次没检测到就绪的socket,就要将其进程(线程)从工作队列中移除,并加入到socket的等待队列中。
socket包含读缓冲区+写缓冲区+等待队列(放线程或eventpoll对象)
当从客户端往服务器端发送数据时,使用TCP/IP协议将通过物理链路、网线发给服务器的网卡设备,网卡的DMA设备将接收到的的数据写入到内存中的一块区域(网卡缓冲区),然后会给CPU发出一个中断信号,CPU执行完当前指令则会保存现场,然后网卡的中断程序就获得了CPU的使用权,然后CPU便开始执行网卡的中断程序,将内存中的缓存区中的数据包拿出,判断端口号便可以判断它是哪个socket的数据,将数据包写入对应的socket的读(输入)缓冲区,去检查对应的socket的等待队列有没有等待着的进程(线程),如果有就将该线程(进程)从socket的等待队列中移除,将其加入工作队列,这时候该进程(线程)就再次拥有了CPU的使用权限,到这里中断程序就结束了。
之后这个进程(线程)就执行select函数再次去检查fd_set就能发现有socket缓冲区中有数据了,就将该socket的fd打标记,这个时候select函数就执行完了,这时候就会给上层返回一个int类型的数值,表示已经就绪的socket的数量或者是发生了错误。这个时候就再进行内核态到用户态的切换,对已经打标记的socket的fd进行处理。
将原本1024bit长度的bitmap(fd_set)换成了数组的方式传入 ,可以 解决原本1024个不够用的情况 ,因为传入的是数组,长度可以不止是1024了,因此socket数量可以更多,在Kernel底层会将数组转换成链表。
在十多年前,linux2.6之前,不支持epoll,当时可能会选择用Windows/Unix用作服务器,而不会去选择Linux,因为select/poll会随着并发量的上升,性能变得越来越低,每次都得检查所有的Socket列表。
1.select/poll每次调用都必须根据提供所有的socket集合,然后就 会涉及到将这个集合从用户空间拷贝到内核空间,在这个过程中很耗费性能 。但是 其实每次的socket集合的变化也许并不大,也许就1-2个socket ,但是它会全部进行拷贝,全部进行遍历一一判断是否就绪。
2.select/poll的返回类型是int,只能代表当前的就绪的socket的数量/发生了错误, 如果还需要知道是哪些socket就绪了,则还需要再次使用系统调用去检查哪些socket是就绪的,又是一次O(n)的操作,很耗费性能 。
1.epoll在Kernel内核中存储了对应的数据结构(eventpoll)。我们可以 使用epoll_create()这个系统调用去创建一个eventpoll对象 ,并返回eventpoll的对象id(epfd),eventpoll对象主要包括三个部分:需要处理的正在监听的socket_fd列表(红黑树结构)、socket就绪列表以及等待队列(线程)。
2.我们可以使用epoll_ctl()这个系统调用对socket_fd列表进行CRUD操作,因为可能频繁地进行CRUD,因此 socket_fd使用的是红黑树的结构 ,让其效率能更高。epoll_ctl()传递的参数主要是epfd(eventpoll对象id)。
3.epoll_wait()这个系统调用默认会 将当前进程(线程)阻塞,加入到eventpoll对象的等待队列中,直到socket就绪列表中有socket,才会将该进程(线程)重新加入工作队列 ,并返回就绪队列中的socket的数量。
socket包含读缓冲区、写缓冲区和等待队列。当使用epoll_ctl()系统调用将socket新加入socket_fd列表时,就会将eventpoll对象引用加到socket的等待队列中, 当网卡的中断程序发现socket的等待队列中不是一个进程(线程),而是一个eventpoll对象的引用,就将socket引用追加到eventpoll对象的就绪列表的尾部 。而eventpoll对象中的等待队列存放的就是调用了epoll_wait()的进程(线程),网卡的中断程序执行会将等待队列中的进程(线程)重新加入工作队列,让其拥有占用CPU执行的资格。epoll_wait()的返回值是int类型,返回的是就绪的socket的数量/发生错误,-1表示发生错误。
epoll的参数有传入一个epoll_event的数组指针(作为输出参数),在调用epoll_wait()返回的同时,Kernel内核还会将就绪的socket列表添加到epoll_event类型的数组当中。
⑵ 如何在linux上添加PHP的socket扩展
增大Linux的socket最大连接数
最近接的项目是模拟多个socket 客户端与服务器进行肢茄通信。由于Linux 系统的限制启灶,在linux/include/linux/posix_types.h文件中有如下的宏定义:
#undef __FD_SETSIZE
#define __FD_SETSIZE 1024
这个宏是对最大文件描述符的定义为1024。当需要1024个以上的fd时,例如select()函数就会侦听出错。因此需要将1024改成需要的数目,但最多不能超过65535。但历旁察仅仅修改这个是不够的。
第二步就需要修改一个进程最大打开的文件数。其具体步骤是:
1、cd /usr/src/linux-2.4/include/linux
2、vi limits.h编辑文件:
#define NR_OPEN 90240 原值为1024
#define OPEN_MAX 10240 原值为1024
3、vi fs.h
#define INR_OPEN 10240 原值为1024
#define NR_FILE 65536 原值为8192,这个值为内存64/1M的比率计算,1G内存计算为:64*1024
#define NR_RESERVED_FILES 128 原值为10.
4、cd /usr/src/linux-2.4/include/net
5、vi tcp.h
#define TCP_LHTABLE_SIZE 128 原值为32.便于listen侦听队列,设大。
设置最大打开文件数与内存相关,太大系统会变慢。
第三步就是编译内核,其具体步骤是:
1. make clean
2. make
3. make dep
4. make bzImage
将bzImage 导入/boot 重启系统即可!
用1024个以上客户端与服务器进行连接,在服务器的终端用netstat |wc 命令可以统计出当前建立的socket的连接数。
⑶ linux单进程如何实现多核cpu多线程分配
linux下的单进程多线程的程序,要实现每个线程平均分配到多核cpu,主要有2个方法
1:利用linux系统自己的线程切换机制,linux有一个服务叫做irqbalance,这个服务是linux系统自带的,默认会启动,这个服务的作用就是把多线程平均分配到CPU的每个核上面,只要这个服务不停止,多线程分配就可以自己实现。但是要注意,如果线程函数内部的有某个循环,且该循环内没有任何系统调用的话,可能会导致这个线程的CPU时间无法被切换出去。也就是占满CPU现象,此时加个系统调用,例如sleep,线程所占的CPU时间就可以切换出去了。
2:利用pthread库自带的线程亲和性设置函数,来设置线程在某个CPU核心上跑,这个需要在程序内部实现。同时注意不要和进程亲和性设置搞混淆了
intpthread_setaffinity_np(pthread_tthread,size_tcpusetsize,
constcpu_set_t*cpuset);
intpthread_getaffinity_np(pthread_tthread,size_tcpusetsize,
cpu_set_t*cpuset);
从函数名以及参数名都很明了,唯一需要点解释下的可能就是cpu_set_t这个结构体了。这个结构体的理解类似于select中的fd_set,可以理解为cpu集,也是通过约定好的宏来进行清除、设置以及判断:
//初始化,设为空
voidCPU_ZERO(cpu_set_t*set);
//将某个cpu加入cpu集中
voidCPU_SET(intcpu,cpu_set_t*set);
//将某个cpu从cpu集中移出
voidCPU_CLR(intcpu,cpu_set_t*set);
//判断某个cpu是否已在cpu集中设置了
intCPU_ISSET(intcpu,constcpu_set_t*set);
⑷ Linux中select poll和epoll的区别
select、poll、epoll都是IO多路复用的机制,但是他们的机制有很大的区别
1、select
select机制刚开始的时候,需要把fd_set从用户空间拷贝到内核空间,并且检测的fd数是有限制的,由FD_SETSIZE设置,一般是1024。
检测的时候,根据timeout,遍历fd_set表,把活跃的fd(可读写或者错误),拷贝到用户空间,
再在用户空间依次处理相关的fd。
这个机制是linux内核很早的版本,epool是根据select,pool基础上优化的,缺点比较多。
缺点:
1)每次调用select的时候需要把fd_set从用户空间拷贝到内存空间,比较耗性能。
2)wait时,需要遍历所有的fd,消耗比较大。
3)select支持的文件数大小了,默认只有1024,如果需要增大,得修改宏FD_SETSIZE值,并编译内核(麻烦,并且fd_set中的文件数多的话,每次遍历的成本就很大)。
2. pool
poll的实现和select非常相似,只是描述fd集合的方式不同,poll使用pollfd结构而不是select的fd_set结构,其他的都差不多。
3. epool
epool是select和poll的改进版本,
* 先是使用int epoll_create(int size)在内存中创建一个指定size大小的事件空间,
* 再使用int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);事件注册函数,注册新的fd到epfd的epool对象空间中,并指明event(可读写啊等等绝租),注意:在注册新事件fd的过程中,也再内核中断处岁禅理程序里注册fd对应的回调函数callback,告诉内核,一旦这个fd中断了,就把它放到ready队列里面去。
* 再使用int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);在epool对象对应的ready队列里取就绪的fd,并并雀兆使用内存映射mmap拷贝到用户空间。
* 再在用户空间依次处理相关的fd。
优点:
1)支持一个进程打开大数目的socket描述符
select 一个进程打开FD是有限制的,由FD_SETSIZE设置,默认值是1024。epool可以打开的FD数可以很大,一般1GB的内存有10万多的FD数,具体数目可以cat /proc/sys/fs/file-max查看。
2) IO效率不随FD数目增加而线性下降
3) 使用mmap加速内核与用户空间的消息传递
⑸ linux中的fd就绪时,会立即回调rollback,那么哪位大牛能帮忙解释下fd就绪的条件是什么
select系统调型戚用原型如下:
#include <sys/select.h>int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout);12
参数readfds, writefds, exceptfds参数分别指向可读卜巧陵、可写和异常事件对应的文件描述符集合。
哪些情况下文件描述符可以被认为是可读、可写或者出现异常,对于select的使用非常关键。
在网络编程中,下列情况下socket可读:
1、socket内核接收缓存区中的字节数大于或等于其低水位标记SO_RCVLOWAT。此时可以无阻塞地读该socket,并且读操作返回的字节数大于0。
2、socket通信对方关闭连接。此时对该socket读操作将返回0。
3、监听socket上有新的连接请求。
4、socket上有未处理的错误。此时我们可以使用getsockopt来读取和清除该错误。
下列情况下socket可写:
1、socket内核发送缓冲区中的可用字节数大于或等于其低水位标记SO_SNDLOWAT。此时我们可以无阻塞写该socket,并且写操作返回的字节数大于0。
2、socket写操作被关闭。对写操作被关闭的socket执行写操作将触发一个SIGPIPE信号。
3、socket使用非阻塞connect连接成功或者失败(超时)之后。
4、socket上有未处理的错误。此时我们可以使用getsockopt来读取和清除该错误。
网络程序中,select能处理的异常情况只有一种宽源:socket上接收到带外数据。
⑹ linux 下的socket怎么测试是否成功
增加对Linux socket连接 最近的一个项目的最大连接数是模拟多个套接字的客户端和服务器之间的通信。 Linux系统由于Linux的限制,/在include / linux / posix_types.h文件中有如下的宏定义: #UNDEF __FD_SETSIZE 的#define __FD_SETSIZE 1024 这个宏是当你需要超过1024个FD,如select()函数将监听错误定义的最大文件描述符1024。所以,你需要改变1024所需要的数量,但不超过65,535。但这是不够的仅仅。 第二步你需要的文件的进程打开的最大数量。具体的步骤是: 1,CD /usr/src/linux-2.4/include/linux 2,六limits.h中编辑文件: 的#define NR_OPEN 90240原1024 1024 的#define OPEN_MAX 10240原值 3值,六fs.h文件 的#define INR_OPEN 10240原值1024 的#define NR_FILE 65536 8192原始值,内存64 / 1M比例计算的值,1G内存的计算公式为:64 * 10. 4 1024 的#define NR_RESERVED_FILES 128原值,CD /usr/src/linux-2.4/include/net BR>五,六tcp.h中 的#define TCP_LHTABLE_SIZE的32 128原值易听听队列,建立大。 - 设为与内存相关的打开文件的最大数量,系统会减慢太多。 第三步是编译内核,具体步骤是: 1.使清洁 2.化妆 3. make dep的 4.做的bzImage 将导入的bzImage /启动重新启动系统! wc命令,以目前在建立套接字连接数统计| 与超过1024个客户端和服务器到服务器的终端使用netstat的连接。
⑺ 100分求linux下C语言端口扫描代码
linux tcp udp 端口扫描源程序
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>做庆
#include <netinet/ip_icmp.h>
#include <stdlib.h>
#include <signal.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#define TRUE 1
#define FALSE 0
#define UDP "UDP"
#define TCP "TCP"
#define tcp "tcp"
#define udp "udp"
typedef struct _GsSockStru{
int fd;
int len;
struct sockaddr_in addr;
}GsSockStru;
static int tcptest( char ip[32], char port[20]);
static int udptest( char ip[32], char port[20]);
void sig_alrm( int signo );
static GsSockStru test_sock;
int
main( int argc, char** argv)
{
char string[64];
char port[20];
char pro[20];
char ip[32];
int res;
int i = 0;
int k = 0;
if( argc>2 || argc<纯慧握2 )
{
printf("鍙傛暟涓碧扰嶆纭?-1\n");
return ( -1 );
}
strcpy( string, argv[1]);
while( *string )
{
if( string[i] == ':' )
break;
pro[k] = string[i];
k++;
i++;
}
pro[k] = '\0';
i++;
k = 0;
while( *string )
{
if( string[i] == ':')
break;
ip[k] = string[i];
k++;
i++;
}
ip[k] = '\0';
i++;
k=0;
while( *string )
{
if( string[i] == '\0')
break;
port[k] = string[i];
k++;
i++;
}
port[k] = '\0';
i++;
memset( &test_sock, 0, sizeof( test_sock ) );
if ( ( strcmp( TCP, pro) != 0 ) && ( strcmp( UDP, pro) != 0 ) && ( strcmp( tcp, pro) != 0 ) && ( strcmp( udp, pro) != 0 ))
{
printf ( "鍙傛暟涓嶆纭?锛?\n" );
return (-1);
}
if ( strcmp( TCP, pro) == 0 || strcmp( tcp, pro) == 0 )
res = tcptest( ip, port );
if ( strcmp( UDP, pro) == 0 || strcmp( udp, pro) == 0 )
res = udptest( ip, port );printf("%d\n",res);
return ( res );
}
int
tcptest( char ip[32], char port[20])
{
int res;
struct timeval tv;
test_sock.fd = socket( AF_INET, SOCK_STREAM, 0 );
if ( test_sock.fd < 0 )
{
printf( "create socket failed -3 \n" );
return ( -3 );
}
memset( &( test_sock.addr ), 0, sizeof( test_sock.addr ) );
test_sock.addr.sin_family = AF_INET;
test_sock.addr.sin_port = htons( atoi( port ) );
inet_pton( AF_INET, ip, &test_sock.addr.sin_addr );
test_sock.len = sizeof( struct sockaddr );
tv.tv_sec = 10;
tv.tv_usec = 0;
setsockopt( test_sock.fd, SOL_SOCKET, SO_RCVTIMEO,
(const char *)&tv, sizeof( tv ) );
res = connect( test_sock.fd,
( struct sockaddr * )( &( test_sock.addr ) ),
test_sock.len );
if ( res < 0 )
{
fprintf( stderr, "connect failed 0\n" );
close( test_sock.fd );
return FALSE;
}
close( test_sock.fd );
return TRUE;
}
int udptest( char ip[32], char port[20])
{
struct icmphdr *icmp_header;
struct sockaddr_in target_info;
int target_info_len;
fd_set read_fd;
int scan_port;
char recvbuf[5000];
struct sockaddr_in target_addr;
int icmp_socket;
int udp_socket;
struct timeval tv;
icmp_header = (struct icmphdr *)(recvbuf+sizeof(struct iphdr));
scan_port = atoi( port );
target_addr.sin_family = AF_INET;
inet_pton( AF_INET, ip, &target_addr.sin_addr );
target_addr.sin_port = htons(scan_port);
if ((udp_socket=socket(AF_INET,SOCK_DGRAM,0))==-1)
{
printf("create socket failed -3\n");
return -3;
}
if ((icmp_socket=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP))==-1)
{
printf("Create raw socket failed -3\n");
return -3;
}
sendto(udp_socket,NULL,0,0,(void *)&target_addr,sizeof(target_addr));
FD_ZERO(&read_fd);
FD_SET(icmp_socket,&read_fd);
tv.tv_sec = 1;
tv.tv_usec = 0;
select(FD_SETSIZE,&read_fd,NULL,NULL,&tv);
for (;;){
if (FD_ISSET(icmp_socket,&read_fd))
{
target_info_len = sizeof(target_info);
recvfrom(icmp_socket,recvbuf,5000,0,
(struct sockaddr *)&target_info,&target_info_len);
if (target_info.sin_addr.s_addr == target_addr.sin_addr.s_addr
&& icmp_header->type == 3 && icmp_header->code<=12)
{
printf("Port %d : Close\n",scan_port);
return (0);
}
}
return (1) ;
}
}
⑻ 求助,LINUX下C 直接被KILLED-CSDN论坛
原来这是stack size 堆大小 达到最大后,就错误了。
在Linux下兆宽,这个其实是可以设置的。
使用 ulimit命令即可设置,不但可以设置这个,还可以设置其他很多限制,使用ulimit -a可以查看当前族塌亮的设置。
ayanmw@ayanmw-desktop:~/server_epoll$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheling priority (-e) 20
file size (blocks, -f) unlimited
pending signals (-i) 16382
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 4096
cpu time (seconds, -t) unlimited
max user processes (-u) unlimited
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
看到stack size居然是8192KB。
程序一般是分为 堆 和 栈,堆 是存放变量名称的地方,比如指针一个指针 本身占用4个字节,指向一个32位地址(64位系统加倍),一般的变量比如int a,这里a的名称也是一个变量,指向存有值的a的空间地址。
而栈就是放数据的地方,只要内存还有,就可以一直分配,不信你可以使用 一个指针,然后malloc(599999)的大小,进程占用内存就有几十MB了。
可以看到,linux下还可以设置文件大小,打开的文件的数量限制。等等。
============================================
以前发现普通用户无法修改ulimit,root用户 可以.
网络搜索得到:
/etc/security/limits.conf
添加
* soft nofile 8192
* hard nofile 8192
可以修改.
CentOS 或 RedHat这个文件的路径貌似是:
[oracle@qs-xezf-db2 ~]$ cat /etc/sysconfig/limits.conf
oracle soft nproc 2047
oracle hard nproc 16384
oracle soft nofile 1024
oracle hard nofile 65536
修改文件应该就可以达到效果了.
有人说:在/root/.bashrc中增加:
ulimit -u unlimited
ulimit -n 10240
不一定管用.- -
sysctl -a 可以查看更多系统配置信息.
1、cat /proc/sys/fs/file-max,可以获得整个系统的文件句柄数目。一般是8192。如果希望增加句柄的总数,可以在脚本/etc/rc.d/rc..local中添加一行:echo 10240 >; /proc/sys/fs/file-max (举例)
不解:使用lsof -f|wc -l 可以看到当前系统的打开文件总数,我的一台邮件服务器在最疯狂的时候曾输出值为4万!!!就是说同衫团时打开了(或未完全关闭)4万个文件链接。而file-max值为8192,为什么??
2、通过设置/etc/security/limits.conf,实现控制每个进程的文件句柄数目。
添加两行: * soft nofile 1024
* hard nofile 8192
确认/etc/pam.d/system-auth文件中有下面一行:session required /lib/security/pam_limits.so
如果说每个进程能打开的文件句柄数目限制为8192,那该进程产生的线程所打开的文件句柄数目是限在该8192内?还是又一个8192呢?
这个问题,最后采取了一个比较简单的方法:
在/boot/.bashrc中加入:
ulimit -u unlimited
ulimit -n 20480
然后所有普通用户的open files都变为20480了,用户最大进程数变为ulimited了。
我看到有的地方说AS3要该进程数只能在
1、设置fd_set支持的最大数量
a、修改/usr/include/bits/typesizes.h
#define __FD_SETSIZE 1024 --->; 65536
b、修改/usr/src/linux/include/linux/posix_types.h
#define __FD_SETSIZE 1024 --->; 65536
2、修改/usr/src/linux/include/linux/fs.h
设置最大打开文件数量(TCP连接数量)
#define INR_OPEN 1024 --->; 65536
#define NR_FILE 8192 --->; 65536
#define NR_RESERVED_FILES 10 --->; 128
3、修改/usr/src/linux/include/net/tcp.h
a、设置TIMEOUT的时间为1秒
#define TCP_TIMEWAIT_LEN (60*HZ) 60 --->; 1*HZ
b、设置在backlog队列里的半连接的重试次数,每次都会花相应的时间,本质上也是减少重试时间
#define TCP_SYNACK_RETRIES 5 --->; 3
然后通过编译内核的方式来增加, 这样比ulimit 更直接修改内核参数.因为内核 是编译出来的.
压力测试:
yuan@yuan-desktop:~$ ab -n 30000 -c 5000 http://localhost/
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost [through 218.19.166.24:3129] (be patient)
socket: Too many open files (24)
提示出错 上网查到是socket系统默认为1024 大于该直就报错 修改.
⑼ Linux如何清空Socket缓冲区
socket不是这么接收数据的 由于socket是以数据流的形式发送数据,接收方不知道对方一次性发送了多少数据,也能保证对方一次性发送的数据能在同一刻接收到,所以Receive方法是这么工作的: 接受一个byye[]类型的参数作为缓冲区,在经过一定的时间后把接收到的数据填充到这个缓冲区里面,并且返回实际接收到数据的长度,这个实际接收到的数据长度有可能为0(没有接收到数据)、大于0小于缓冲区的长度(接收到数据,但是没有我们预期的多)、等于缓冲区的长度(说明接收到的数据大于等于我们预期的长度)。 每次接收缓冲区都用同一个byte[] byteMessage,并且你没有检查接收到的数据长度,所以第一次你接收到的数据是123456,第二次你只接收到了8,但是缓冲区里面还有23456,所以加起来就是823456了。 socket接收缓冲区的大小有讲究,设置大了接收起来慢,因为它要等尽可能多的数据接收到了再返回;设置小了需要重复多次调用接收方法才能把数据接收完,socket有个属性,标识了系统默认的接收缓冲区大小,可以参考这个! 还有就是用recv读取,但是由于不知道缓存里有多少数据,如果是阻塞模式,到最后必然等到超时才知道数据已经读取完毕,这是个问题。 另一个是用fgetc,通过返回判断是否是feof: whlie (1) { a=fgetc(f);if (feof(f)) break;//… b=fgetc(f);if (feof(f)) break;//…}当然,我不知道读取完毕后最后一次调用fgetc会不会堵塞,需要测试。 在非阻塞模式下,我们用recv就可以轻松搞定了,但是阻塞模式下,由于我们不知道缓冲区有多少数据,不能直接调用recv尝试清除。 使用一个小小的技巧,利用select函数,我们可以轻松搞定这个问题: select函数用于监视一个文件描述符集合,如果集合中的描述符没有变化,则一直阻塞在这里,直到超时时间到达;在超时时间内,一旦某个描述符触发了你所关心的事件,select立即返回,通过检索文件描述符集合处理相应事件;select函数出错则返回小于零的值,如果有事件触发,则返回触发事件的描述符个数;如果超时,返回0,即没有数据可读。 重点在于:我们可以用select的超时特性,将超时时间设置为0,通过检测select的返回值,就可以判断缓冲是否被清空。通过这个技巧,使一个阻塞的socket成了‘非阻塞’socket. 现在就可以得出解决方案了:使用select函数来监视要清空的socket描述符,并把超时时间设置为0,每次读取一个字节然后丢弃(或者按照业务需要进行处理,随你便了),一旦select返回0,说明缓冲区没数据了(“超时”了)。 struct timeval tmOut;tmOut.tv_sec = 0;tmOut.tv_usec = 0;fd_set fds;FD_ZEROS(&fds);FD_SET(skt, &fds); int nRet; char tmp[2]; memset(tmp, 0, sizeof(tmp)); while(1) { nRet= select(FD_SETSIZE, &fds, NULL, NULL, &tmOut);if(nRet== 0) break;recv(skt, tmp, 1,0);} 这种方式的好处是,不再需要用recv、recvfrom等阻塞函数直接去读取,而是使用select,利用其超时特性检测缓冲区是否为空来判断是否有数据,有数据时才调用recv进行清除。 有人说同样可以用recv和socket的超时设置去清空啊,这个没错,但是你需要直接对socket描述符设置超时时间,而为了清空数据而直接修改socket描述符的属性,可能会影响到其他地方的使用,造成系统奇奇怪怪的问题,所以,不推荐使用。
⑽ linux系统,如何设置最大网络连接数量
linux设置最大网络连接数量有很多中方法:
1、直接用ulimit命令
ulimit -n 8192
2、修改/proc/sys/net/ipv4/ip_conntrack_max为8192
或者是/etc/sysctl.conf中加入ip_conntrack_max=8192
3、请首先编祥亏尘辑/usr/include/bits/types.h 文件,改变__FD_SETSIZE 的值:
#define _ _FD_SETSIZE 8192
下一步,使用这空渗个命令增加内核文件描述符的限制:
# echo 8192 > /proc/sys/fs/file-max
最后,增加进程文件描述符谨禅的限制,在即将编译squid 的同一个shell 里执行:
sh# ulimit -Hn 8192