美文网首页
linux多进程程序示例(linux process examp

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

作者: help_youself | 来源:发表于2021-03-18 16:03 被阅读0次

    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

    相关文章

      网友评论

          本文标题:linux多进程程序示例(linux process examp

          本文链接:https://www.haomeiwen.com/subject/qpqpcltx.html