Linux下基於訊號和共享記憶體實現程序池

2021-10-11 04:07:23 字數 3975 閱讀 3015

為了實現程序池,我們主要需要考慮以下幾個點

1:如何進行程序間通訊

2:程序間如何共享資料

關於程序間通訊,有很多種方式,比如說管道,訊號,socket,共享記憶體,訊息佇列等,本文主要基於訊號共享記憶體來實現程序間通訊。

對應linux的函式原型為:

int kill(pid_t pid, int sig); //傳送訊號

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); //訊號響應相關函式

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); //共享記憶體

大體思路是:

對於父程序:父程序建立一定數量的子程序,父程序負責接受子程序發給自己的訊號,接收到子程序發給自己的訊號的時候,去統計共享記憶體中子程序的狀態,如果子程序的空閒數量超過了最大值,便殺死超出數量的空閒子程序,如果子程序空閒數量小於最小值,便新增對應數量的程序。

對於子程序:子程序負責做任務,然後在不同的時機中給父程序發訊號,告訴父程序說子程序的狀態是忙碌的還是空閒的。

服務端serv.c

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

//自定義訊號

#define signotify sigusr1

#define min_process 5

#define max_process 10

#define max_client_size 20

#define buf_max_size 128

//程序狀態列舉

enum

;//程序資訊

struct proc_info_st

;static

struct proc_info_st *proc_pool;

static

int serv_sock;

//子程序通知父程序的空跑函式

static

void

notify_handler

(int signum)

static

int idle_num =0;

//空閒的數量

static

int busy_num =0;

//忙的數量

static

intget_free_pos()

}return-1

;}static

void

err_exit

(int flag,

const

char

*msg)

}static

void

do_job

(int index)

}//嘗試新增多個任務

void

try_add_job

(int count)

pid_t pid =

fork()

;err_exit

(pid <0,

"fork error");

if(pid ==0)

else}}

void

try_del_job

(int count)}}

}static

void

recout_proc_state()

if(proc_pool[i]

.state == idle_state)

else

} idle_num = idle;

busy_num = busy;

}static

void

print_proc_state()

if(proc_pool[i]

.state == busy_state)

else

}putchar

('\n');

}static

void

init_proc()

//最小預留的程序

try_add_job

(min_process);}

static sigset_t old_sigset;

//清理

static

void

exit_func()

intmain()

else

if(idle_num > max_process)

//列印

print_proc_state()

;}exit(0

);}

客戶端 cli.c

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

intmain()

struct sockaddr_in serv_addr;

socklen_t socklen =

sizeof

(struct sockaddr_in)

; serv_addr.sin_family = af_inet;

serv_addr.sin_port =

htons

(8888);

inet_pton

(af_inet,

"192.168.66.66"

,&serv_addr.sin_addr.s_addr);if

(connect

(sd,

(struct sockaddr *

)&serv_addr,

sizeof

(serv_addr)

)<0)

char buf[

1024]=

;read

(sd, buf,

sizeof

(buf));

printf

("recv data:%s\n"

, buf)

;exit(0

);}

分別編譯客戶端和服務端的**

gcc serv.c -o serv

gcc cli.c -o cli

然後執行能看到如下效果

服務端執行

./serv

輸出

iiiiii--------------

iiiiii--------------

biiiii--------------

bbiiiii-------------

....

..

客戶端執行

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

輸出

recv data:current server time[1606966015]

recv data:current server time[1606966016]

recv data:current server time[1606966017]

共享記憶體和訊號

1 共享記憶體概述 共享記憶體允許兩個或更多程序共享一給定的儲存區。因為資料不需要在各個程序之間複製,所以這是最快的一種程序間通訊方式。使用共享記憶體時的關鍵點在於如何在多個程序之間對一給定的儲存區進行同步訪問。例如若乙個程序正在將資料放入共享記憶體區,則在它做完這一操作之前,其他程序不應該去取這些...

Linux訊號量和共享記憶體

include include include include include include include include static intset semvalue void static intsemaphore p void static intsemaphore v void stat...

Linux下基於POSIX標準的共享記憶體操作示例

對於程序間通訊,之前一直是用管道進行實現。比如父子程序間使用pipe,無血緣關係的程序可以使用fifo。從來沒有想過使用共享記憶體,為什麼呢?大家還記得這本書吧 unix環境高階程式設計 上面講解了關於共享記憶體的操作,說實話,太麻煩了,真的不好用 有好多繁雜的介面,比如shmget,shmat,s...