Run ns3 with multiple processes

17 篇文章 0 订阅

采用多进程的模式运行ns3

first version

ns3-process.cc

#include <iostream>
#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include "ns3/ping-pong-module.h"
#include "ns3/log.h"
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;
}

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;
}
using namespace ns3;
int main(int argc, char *argv[]){
    uint32_t last=TimeMillis();
    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];
    memset(user,0,2*sizeof(abc_user_t));
    user[0].start=0;
    user[0].count=20;
    user[1].start=30;
    user[1].count=10;
    user_task_fun=ns3_main;
    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;
        }
    }
    uint32_t delta=TimeMillis()-last;
    std::cout<<"run_time:"<<delta<<std::endl;
    return 0;
}

Run

./waf --run  "scratch/ns3-p0"

second version

Processing request from socket

 In this version, a client is provided to send requst to ns3-p1, which binds on port 2233 to start simulation.
  The code can be downloaded on github [6].

Reference:
[1] epoll-example
[2] waitpid()函数详解
[3] Linux errno 错误对照表
[4] 多线程程序运行一次,关了之后,第二次就打不开了
[5] Socket中SO_REUSEADDR详解
[6] code-repo

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值