Linux高阶——1124—多进程多任务多线程多任务多路IO转接技术
目录
1、多进程多任务服务器
代码
2、多线程多任务(阻塞IO)
代码
3、关于多路IO转接技术(select、poll、epoll)
关于服务器程序的IO处理
socket
对网络IO处理的过程
1、多进程多任务服务器
代码
#include<sock.c>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>
#include<pthread.h>
#include<sys/wait.h>
#define server_ip "192.168.5.133"
#define server_port 9090
void sig_wait(int n)
{
pid_t zpid;
while((zpid=waitpid(-1,NULL,WNOHANG))>0)
{
printf("thread 0x%x wait success,zpid %d\n",(unsigned int)pthread_self(),zpid);
}
}
void * thread_wait(void * arg)
{
struct sigaction act,oact;
act.sa_handler=sig_wait;
act.sa_flags=0;
sigemptyset(&act.sa_mask);
sigaction(SIGCHLD,&act,&oact);
sigprocmask(SIG_SETMASK,&act.sa_mask,NULL);
while(1)
sleep(1);
}
int main()
{
sigset_t set,oset;
sigemptyset(&set);
sigaddset(&set,SIGCHLD);
sigprocmask(SIG_SETMASK,&set,&oset);
pthread_t tid;
pthread_create(&tid,NULL,thread_wait,NULL);
pid_t pid;
struct sockaddr_in client_addr;
int server_sock;
int client_sock;
server_sock=net_initializer(NULL,server_port,128);
socklen_t addrlen;
printf("PROCESS MOD Servers Running...\n");
char cip[16];
ssize_t len;
client_info cf;
char buf[1500];
char* msg="Please try again\n";
char tm[1024];
while(1)
{
addrlen=sizeof(client_addr);
if((client_sock=ACCEPT(server_sock,(struct sockaddr*)&client_addr,&addrlen))>0)
{
pid=fork();
}
if(pid>0)
{
cf.sockfd=client_sock;
inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,cf.ip,16);
cf.port=ntohs(client_addr.sin_port);
first_response(cf);
}
else if(pid==0)
{
while((len=RECV(client_sock,buf,sizeof(buf),0))>0)
{
if((strcmp(buf,"time\n"))==0)
{
get_time(tm);
SEND(client_sock,tm,strlen(tm),MSG_NOSIGNAL);
bzero(tm,sizeof(tm));
}
else
{
SEND(client_sock,msg,strlen(msg),MSG_NOSIGNAL);
}
bzero(buf,sizeof(buf));
}
if(len==0)
{
printf("client exit\n");
close(client_sock);
exit(0);
}
}
else
{
perror("fork call failed");
exit(0);
}
}
close(server_sock);
printf("server done\n");
return 0;
}
2、多线程多任务(阻塞IO)
多线程模型,可以在内存调度开销更小的情况下,完成并发任务,提高CPU使用率,加快执行效率
代码层面与多进程也比较相似,当用户递达,为客户端创建处理线程,处理线程随客户端持续
代码
#include<sock.c>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>
#include<pthread.h>
#include<sys/wait.h>
#define server_ip "192.168.5.133"
#define server_port 9090
void * thread_customer(void * arg)
{
int client_sock=*(int*)arg;
char* msg="Please try again\n";
int len;
char buf[1500];
char tm[1024];
pthread_detach(pthread_self());
while((len=RECV(client_sock,buf,sizeof(buf),0))>0)
{
if((strcmp(buf,"time\n"))==0)
{
get_time(tm);
SEND(client_sock,tm,strlen(tm),MSG_NOSIGNAL);
bzero(tm,sizeof(tm));
}
else
{
SEND(client_sock,msg,strlen(msg),MSG_NOSIGNAL);
}
bzero(buf,sizeof(buf));
}
if(len==0)
{
printf("client exit\n");
close(client_sock);
exit(0);
}
}
int main()
{
struct sockaddr_in client_addr;
int server_sock;
int client_sock;
server_sock=net_initializer(NULL,server_port,128);
socklen_t addrlen;
printf("PROCESS MOD Servers Running...\n");
char cip[16];
ssize_t len;
client_info cf;
pthread_t tid;
while(1)
{
addrlen=sizeof(client_addr);
if((client_sock=ACCEPT(server_sock,(struct sockaddr*)&client_addr,&addrlen))>0)
{
pthread_create(&tid,NULL,thread_customer,(void*)&client_sock);
cf.sockfd=client_sock;
inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,cf.ip,16);
cf.port=ntohs(client_addr.sin_port);
first_response(cf);
}
}
close(server_sock);
printf("server done\n");
return 0;
}
相比于多进程,多线程模型更轻量,无论是内存占用还是调度速度,但是几点需要注意
首先是稳定性问题,多进程模式较为稳定,某个进程异常退出与其他进程无关,但是多线程中,如果某个线程异常可能会导致进程退出
多线程要考虑线程同步、线程安全、死锁避免等问题,在一些用户级线程下,线程无法得到时间片,所以在并发模型选择时要仔细斟酌,而后选择多进程亦或多线程
3、关于多路IO转接技术(select、poll、epoll)
多路IO转接技术——sock监听技术
关于服务器程序的IO处理
一个服务器连接了1000个客户端,每个客户端会产生一个socket
单进程非阻塞模式会遍历所有client_sock,并且尝试读写
多进程模式,每个进程分配一个client_sock,此进程读写
但当前的单进程和多进程均为主动处理IO,但这种主动方法不合理,当sock无事件时,不应该主动读取,浪费开销
client_sock——当sock无事件时,不应该主动等待,等就绪时再处理
server_sock——当sock无连接时,等有连接时再处理
socket
每个sock都包含三种标准事件,IN(读事件)、OUT(写事件)、ERR(异常事件)
当缓冲区不为空,有数据待读,对应的client_sock触发读事件
当sock将数据写入sock缓冲区,等待发送时,触发写事件
当操作的sock出现异常,触发异常事件
对网络IO处理的过程
1、sock监听设置,准备监听(IN、OUT、ERR)
2、开始监听(Select or Poll Epoll)
3、sock就绪
4、处理就绪
5、处理数据,读写sock,或三次握手
6、处理完毕——数据读取成功,连接成功
上述只表示IO监听与处理过程,与数据处理协议处理无关
IO监听和数据处理分离