OVS vswitchd 模块分析(1)

本文详细介绍了Open vSwitch (OVS) 中vswitchd子进程如何通过RPC服务进行通信。首先,`worker_start`函数创建了一个Unix域套接字流管道,用于父子进程间通信。子进程作为RPC服务器,处理来自父进程的请求。接着,通过`unixctl_server_create`创建Unix套接字控制服务器,监听指定路径或默认路径下的socket文件,供ovs-appctl命令使用。整个过程涉及到了进程创建、套接字通信和RPC协议等关键技术。
摘要由CSDN通过智能技术生成

1.开启RPC服务。
在当前进程中启动一个worker process作为子进程,当前只支持一个,所以要确保只被调用一次并且要在客户程序主循环中呼叫 worker_run() 和worker_wait() 。worker_start 定义在lib/worker.c,工作流程:通过socketpair函数(仅适用于Unix域套接字)创建一个流管道work_fds[0],work_fds[1],然后通过fcntl设置为非阻塞状态;接下来 fork_and_clean_up在fork子进程中做一些工作。daemonize_post_detach()如果有守护进程的相关配置,那么这个方法就会响应这些,即如果有 --detach ,--no-chdir的话那么detach=true,chdir_=false (关于这些定义在daemon.c中),然后关闭标准文件描述符。接下来就是子进程作为RPC server和主进程沟通(child:work_fd[1]<->parent:work_fds[0]) 。

void   worker_start(void){
    int work_fds[2];

    assert(client_sock < 0);

    xsocketpair(AF_UNIX, SOCK_STREAM, 0, work_fds);   //--->socketpair()
    xset_nonblocking(work_fds[0]);  // fcntl() 
    xset_nonblocking(work_fds[1]);

    if (! fork_and_clean_up()) {
        /* In child (worker) process. */
         daemonize_post_detach();
        close(work_fds[0]);
        worker_main(work_fds[1]);
        NOT_REACHED();
    }

    /* In parent (main) process. */
    close(work_fds[1]);
    client_sock = work_fds[0];
     rxbuf_init(&client_rx);
}

fork_and_clean_up定义在lib/daemon.c中,调用fork函数,并且在子进程中: 启动内部计时器,确保即使没有调用time_refresh()时间也会前进,fork生成的子进程不会继承父进程的内部计时器,所以要确保在fork()之后呼叫这个函数;lockfile_postfork()确保现在锁定的lockfile解开(就是关闭相应的文件描述符,而后从hmap locktable中移除),这在fork之后调用很有意义,因为 被fork创建的子进程不在持有父进程的锁
/* Post-fork, but before returning, this function calls a few other functions  that are generally useful if the child isn't planning to exec a new process. */
pid_t  fork_and_clean_up(void){
    pid = fork();
    if (pid > 0) {
        /* Running in parent process. */
        fatal_signal_fork();   //??
    } else if (!pid) {
         time_postfork();
        lockfile_postfork();

    } else {
        VLOG_FATAL("fork failed (%s)", strerror(errno));
    }
     return pid;
}

在worker.c中定义的RPC 请求/回复header 和 接口实际上就是RPC server和client的通信协议 (在这里header和payload都符合openflow的那一套)。在worker_main中,初始化一个rxbuf,接着rxbuf_run()就会将接收信息,构造rx;然后就调用 request callback func(具体实现没看到?)。

static void   worker_main(int fd){
    struct rxbuf rx;
    server_sock = fd;
    subprogram_name = "worker";
    proctitle_set("worker process for pid %lu", (unsigned long int) getppid());
    VLOG_INFO("worker process started");

     rxbuf_init(&rx);
    for (;;) {
        int error;

        error =  rxbuf_run(&rx, server_sock, sizeof(struct worker_request));
        if (!error) {
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值