linux多进程程序示例(linux process examp

2021-03-18  本文已影响0人  help_youself

Introduction

 代码基本上是抄袭自nginx。在此表示感谢。The code here owns much to nginx. With thanks to author for such greate contribution.

Code

process_test.cc

#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <memory.h>
#include <chrono>
#include <errno.h>
#include <signal.h>
#include <sys/types.h> //pid_t
#include <sys/wait.h>
inline int64_t WallTimeNowInUsec(){
    std::chrono::system_clock::duration d = std::chrono::system_clock::now().time_since_epoch();    
    std::chrono::microseconds mic = std::chrono::duration_cast<std::chrono::microseconds>(d);
    return mic.count(); 
}
inline int64_t TimeMillis(){
    return WallTimeNowInUsec()/1000;
}

#define abc_signal_helper(n)     SIG##n
#define abc_signal_value(n)      abc_signal_helper(n)
#define abc_str_value_helper(n)   #n
#define abc_str_value(n)          abc_str_value_helper(n)
#define ABC_SHUTDOWN_SIGNAL      QUIT
#define ABC_TERMINATE_SIGNAL     TERM
typedef struct {
    int     signo;
    char   *signame;
    char   *name;
    void  (*handler)(int signo, siginfo_t *siginfo, void *ucontext);
}abc_signal_t;
static volatile bool g_running=true;
static void abc_signal_handler(int signo, siginfo_t *siginfo, void *ucontext){
    switch(signo){
        case abc_signal_value(ABC_SHUTDOWN_SIGNAL):
        case abc_signal_value(ABC_TERMINATE_SIGNAL):
        case SIGINT:
        case SIGHUP:
        case SIGTSTP:
            g_running=false;
            std::cout<<"signal "<<signo<<std::endl;
            break;
        default:
            break;
    }
}
abc_signal_t  signals[] ={
    { abc_signal_value(ABC_TERMINATE_SIGNAL),
      (char*)"SIG" abc_str_value(ABC_TERMINATE_SIGNAL),
      (char*)"stop",
      abc_signal_handler},
    {abc_signal_value(ABC_SHUTDOWN_SIGNAL),
      (char*)"SIG" abc_str_value(ABC_SHUTDOWN_SIGNAL),
      (char*)"quit",
      abc_signal_handler},
    { SIGINT, (char*)"SIGINT", (char*)"", abc_signal_handler },
    { SIGHUP, (char*)"SIGHUP", (char*)"", abc_signal_handler },
    { SIGTSTP, (char*)"SIGTSTP",(char*)"", abc_signal_handler },
    { 0, NULL, (char*)"", NULL}
};
int abc_init_signals()
{
    abc_signal_t      *sig;
    struct sigaction   sa;

    for (sig = signals; sig->signo != 0; sig++) {
        memset(&sa, 0,sizeof(struct sigaction));

        if (sig->handler) {
            sa.sa_sigaction = sig->handler;
            sa.sa_flags = SA_SIGINFO;
        } else {
            sa.sa_handler = SIG_IGN;
        }
        sigemptyset(&sa.sa_mask);
        if (sigaction(sig->signo, &sa, NULL) == -1) {
            std::cout<<"error init signal "<<sig->name<<std::endl;
        }
    }
    return 0;
}


#define ABC_PRIV_SZ 64
#define ABC_MAX_PROCESSES 4
#define ABC_INVALID_PID  -1
#define abc_errno                  errno
#define abc_getpid   getpid
#define abc_getppid  getppid

typedef pid_t abc_pid_t;
typedef struct{
    abc_pid_t pid;
    char priv[ABC_PRIV_SZ];
}abc_process_t;

abc_process_t abc_processes[ABC_MAX_PROCESSES];
int abc_process_slot;
int abc_last_process;
abc_pid_t     abc_pid;
abc_pid_t     abc_parent;
typedef void (*abc_task_fun_t)(void *user_data);
abc_task_fun_t user_task_fun=nullptr;
void abc_worker_process(){
    abc_init_signals();
    abc_process_t *ptr=&abc_processes[abc_process_slot];
    if(user_task_fun){
        user_task_fun((void*)ptr->priv);
    }
}
abc_pid_t abc_spawn_process(const char*priv,int sz){
    abc_pid_t pid;
    if(sz<0||sz>ABC_PRIV_SZ){
        return ABC_INVALID_PID;
    }
    int s=0;
    for(s=0;s<abc_last_process;s++){
        if(-1==abc_processes[s].pid){
            break;
        }
    }
    abc_process_slot=s;
    if(priv&&sz>0){
        memcpy(abc_processes[s].priv,priv,sz);
    }
    pid = fork();
    switch(pid){
        case -1:{
            std::cout<<"fork failed"<<std::endl;
            return ABC_INVALID_PID;
        }
        case 0:{
            abc_parent=abc_pid;
            abc_pid=abc_getpid();
            abc_worker_process();
            break;
        }
        default:
            break;
    }
    if(0==pid){
        exit(0);
    }else{
        abc_processes[s].pid=pid;
        abc_last_process++;
    }
    return pid;
}
void abc_signal_workers(int signo){
    for(int i=0;i<abc_last_process;i++){
        abc_pid_t pid=abc_processes[i].pid;
        if(pid>0){
            if(-1==kill(pid,signo)){
                std::cout<<"kill erorr"<<strerror(abc_errno)<<std::endl;
            }
            int status=0;
            if(-1==waitpid(pid,&status,0)){
                std::cout<<"waitpid erorr"<<strerror(abc_errno)<<" "<<status<<std::endl;
            }
            abc_processes[i].pid=-1;
        }
    }
    abc_last_process=0;    
}
int abc_worker_status(abc_pid_t pid){
    int status;
    int ret=waitpid(pid,&status,WNOHANG);
    if(-1==ret){
        std::cout<<pid<<strerror(abc_errno)<<std::endl;
    }
    return ret;
}
int abc_alive_workers(){
    int counter=abc_last_process;
    int sig_term=abc_signal_value(ABC_TERMINATE_SIGNAL);
    int n=counter;
    for(int i=n-1;i>=0;i--){
        abc_pid_t pid=abc_processes[i].pid;
        int alive=1;
        if(pid>0){
            if(pid==abc_worker_status(pid)){
                kill(pid,sig_term);
                abc_processes[i].pid=-1;
                counter--;
                alive=0;
            }
        }else{
            counter--;
            alive=0;
        }
        if(0==alive&&i==abc_last_process-1){
            abc_last_process--;
        }
    }
    return counter;
}

typedef struct{
    int data1;
    int data2;
}abc_user_t;
void test_task(void *priv){
    abc_user_t *user=(abc_user_t*)priv;
    int count=0;
    int32_t last=TimeMillis();
    while(g_running){
        int32_t now=TimeMillis();
        int32_t delta=now-last;
        last=now;
        std::cout<<abc_pid<<" "<<user->data1<<" "<<count<<" "<<delta<<std::endl;
        if(count>10){
            break;
        }
        usleep(30000);
        count++;
    }
}
int main(){
    abc_init_signals();
    abc_process_slot=0;
    abc_last_process=0;
    memset((void*)abc_processes,0,sizeof(abc_processes));
    abc_parent=abc_getppid();
    abc_pid=abc_getpid();
    int n=2;
    int alive=0;
    abc_user_t user[2];
    user[0].data1=1;
    user[0].data2=2;
    user[1].data1=3;
    user[1].data2=4;
    user_task_fun=test_task;
    for(int i=0;i<n;i++){
        if(abc_spawn_process((const char*)&user[i],sizeof(abc_user_t))>0){
            alive++;
        }
    }
    for(int i=0;i<ABC_MAX_PROCESSES;i++){
        abc_pid_t pid=abc_processes[i].pid;
        if(pid>0){
            int ret=abc_worker_status(pid);
            std::cout<<"check "<<pid<<" "<<ret<<std::endl;
        }
    }
    while(g_running){
        if(0==abc_alive_workers()){
            break;
        }
    }
    for(int i=0;i<abc_last_process;i++){
        abc_pid_t pid=abc_processes[i].pid;
        if(pid>0){
            int ret=abc_worker_status(pid);
            std::cout<<"check "<<pid<<" "<<ret<<std::endl;
        }
    }
    return 0;
}

Build

g++ -o t_pro process_test.cc

上一篇下一篇

猜你喜欢

热点阅读