简易动态进程池

/************proto.h********************/

#ifndef __PROTO_H__
#define __PROTO_H__

#define FORMAT "%ld\n"
#define MINIDLEPROCNUM 5
#define MAXIDLEPROCNUM 10
#define MAXPROCNUM 20

#define SERVERPORT "4096"

#endif

 

/************server.c********************/

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <time.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/mman.h>
#include "proto.h"

#define BUFFSIZE 64
#define IPSIZE 40

enum proc_state
{
IDLE_STATE = 0,
BUSY_STATE,
MAX_STATE
};

struct proc_st
{
int state;
pid_t pid;
};

static int idle_num =0;
static int busy_num =0;
static struct proc_st *procArray;
static int sockfd;

static void proc_work(int pos);
static int add_one_worker(void);
static int del_one_worker(void);
static int find_pos(void);
static void show_workProc(void);

static void usr2_handler(int num)
{
fprintf(stdout,"get signal\n");
}

int main()
{
struct sigaction sa, osa;
sigset_t set, oset;
struct sockaddr_in laddr;
int val =1;
int pos;

sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_NOCLDWAIT;
sigaction(SIGCHLD, &sa, &osa);

sa.sa_handler = usr2_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGUSR2, &sa, &osa);

sigemptyset(&set);
sigaddset(&set, SIGUSR2);
if(sigprocmask(SIG_BLOCK, &set, &oset)<0)
{
perror("sigprocmask()");
exit(1);
}

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd<0)
{
perror("socket()");
exit(1);
}

if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val , sizeof(val))<0)
{
perror("setsockopt()");
exit(1);
}

laddr.sin_family = AF_INET;
laddr.sin_port = htons(atoi(SERVERPORT));
inet_pton(AF_INET,"0.0.0.0",&laddr.sin_addr);
if(bind(sockfd, (void *)&laddr, sizeof(laddr))<0)
{
perror("bind()");
exit(1);
}

if(listen(sockfd, 100)<0)
{
perror("listen()");
exit(1);
}

procArray = mmap(NULL, sizeof(struct proc_st)*MAXPROCNUM, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
if(procArray == MAP_FAILED)
{
perror("mmap()");
exit(1);
}
for(int i=0; i<MAXPROCNUM; i++)
{
procArray[i].state =-1;
}

for(int i=0;i<MINIDLEPROCNUM;i++)
{
pid_t pid;

pos = find_pos();
if(pos <0)
{
fprintf(stderr, "find pos failed\n");
exit(1);
}

//创建进程
pid = fork();
if(pid<0)
{
perror("fork()");
exit(1);
}
if(pid ==0)
{
proc_work(pos);
}
else
{
procArray[pos].state = IDLE_STATE;
procArray[pos].pid = pid;
idle_num ++;
}
}

while(1)
{
//等待SET集信号
sigsuspend(&oset);

if(idle_num <MINIDLEPROCNUM)
{
add_one_worker();
}
if(idle_num >MAXIDLEPROCNUM)
{
del_one_worker();
}
show_workProc();
}
sigprocmask(SIG_SETMASK, &oset, NULL);
close(sockfd);

exit(0);
}

//while true; do (./client &); sleep 1; done

static int add_one_worker(void)
{
pid_t pid;
int pos;

if((idle_num + busy_num)>= MAXPROCNUM)
return -1;

pos = find_pos();
if(pos <0)
{
fprintf(stderr, "find pos failed\n");
exit(1);
}

//创建进程
pid = fork();
if(pid<0)
{
perror("fork()");
exit(1);
}
if(pid ==0)
{

proc_work(pos);
}
else
{
procArray[pos].state = IDLE_STATE;
procArray[pos].pid = pid;
idle_num ++;
}

return 0;
}

static int del_one_worker(void)
{
int i;

for(i=0;i<MAXPROCNUM;i++)
{
if(procArray[i].state == IDLE_STATE)
{
kill(procArray[i].pid, SIGQUIT);
procArray[i].state = -1;
idle_num --;
return 0;
}
}

return 0;
}

static void show_workProc(void)
{
int idle_cal =0, busy_cal =0;
for(int i=0;i<MAXPROCNUM;i++)
{
if(procArray[i].state == -1)
{
//进程未创建
putchar(' ');
}
else if(procArray[i].state == IDLE_STATE)
{
//进程空闲
putchar('.');
idle_cal ++;
}
else if(procArray[i].state == BUSY_STATE)
{
//进程忙碌
putchar('x');
busy_cal ++;
}
}
putchar('\n');
idle_num =idle_cal;
busy_num =busy_cal;
}

static int find_pos(void)
{
int i;

for(i=0;i<MAXPROCNUM;i++)
{
if(procArray[i].state == -1)
return i;
}

return -1;
}

static void proc_work(int pos)
{
int clientfd;
struct sockaddr_in raddr;
socklen_t lenth =0;
time_t currentTime;
char buff[BUFFSIZE];
char ip[IPSIZE];

while(1)
{
clientfd = accept(sockfd, (void *)&raddr, &lenth);
if(clientfd<0)
{
perror("accept()");
continue;
}

//显示客户端信息
// inet_ntop(AF_INET, raddr.sin_addr, ip, IPSIZE);
// sprintf(stdout,"ip:%s port:%d\n",ip, ntohs(raddr.sin_port));

//切换进程状态
procArray[pos].state = BUSY_STATE;
kill(getppid(), SIGUSR2);

//发送时间戳
currentTime = time(NULL);
snprintf(buff, BUFFSIZE, FORMAT, currentTime);
send(clientfd, buff, BUFFSIZE, 0);
sleep(5);
close(clientfd);

//切换进程状态
procArray[pos].state = IDLE_STATE;
kill(getppid(), SIGUSR2);
}
exit(0);
}

 

/********************client.c********************/

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <time.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include "proto.h"

#define BUFFSIZE 40

int main()
{
struct sockaddr_in raddr;
int val =1;
int sockfd;
char buff[BUFFSIZE] = {0};

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd<0)
{
perror("socket()");
exit(1);
}

raddr.sin_family = AF_INET;
raddr.sin_port = htons(atoi(SERVERPORT));
inet_pton(AF_INET,"0.0.0.0",&raddr.sin_addr);

if(connect(sockfd, (void *)&raddr, sizeof(raddr))<0)
{
perror("connect()");
exit(1);
}

recv(sockfd, buff, BUFFSIZE, 0);
fprintf(stdout, "%s", buff);

close(sockfd);

exit(0);
}

posted @   *^VV^*  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示