2017-01-29 4 views
3

Есть несколько вопросов и ответов, как это сделать, но оба процесса должны сотрудничатьShare сокет между несвязанными процессами как Systemd

и т.д.

В systemd, t здесь есть функция socket activation, вы просто открыли и подготовили файл дескриптор в своем процессе без какого-либо сотрудничества. Вы можете просто использовать дескриптор файла 3 (SD_LISTEN_FDS_START), и он уже активирован socket by systemd.

Как это сделать systemd? Я не могу найти подходящий исходный код.

Edit:

Я знаю, как писать Systemd сокет активизировать услугу, но я заинтересован в процессе прохождения дескриптора файла в моей форме службы в systemd точку зрения.

E.g. если я хотел бы написать свой собственный активатор сокета, который ведет себя точно так же, как systemd.

ответ

2

systemdне связан с процессами, совместно использующими сокеты. systemd запускает и контролирует всю систему, поэтому он может легко передавать дескрипторы файла сокета в течение exec(). systemd слушает от имени служб и всякий раз, когда будет происходить соединение, экземпляр соответствующей службы будет порожден. Here является реализация:

int main(int argc, char **argv, char **envp) { 
     int r, n; 
     int epoll_fd = -1; 

     log_parse_environment(); 
     log_open(); 

     r = parse_argv(argc, argv); 
     if (r <= 0) 
       return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE; 

     r = install_chld_handler(); 
     if (r < 0) 
       return EXIT_FAILURE; 

     n = open_sockets(&epoll_fd, arg_accept); 
     if (n < 0) 
       return EXIT_FAILURE; 
     if (n == 0) { 
       log_error("No sockets to listen on specified or passed in."); 
       return EXIT_FAILURE; 
     } 

     for (;;) { 
       struct epoll_event event; 

       r = epoll_wait(epoll_fd, &event, 1, -1); 
       if (r < 0) { 
         if (errno == EINTR) 
           continue; 

         log_error_errno(errno, "epoll_wait() failed: %m"); 
         return EXIT_FAILURE; 
       } 

       log_info("Communication attempt on fd %i.", event.data.fd); 
       if (arg_accept) { 
         r = do_accept(argv[optind], argv + optind, envp, event.data.fd); 
         if (r < 0) 
           return EXIT_FAILURE; 
       } else 
         break; 
     } 
     ... 
} 

После того, как соединение приходит, он будет вызывать do_accept():

static int do_accept(const char* name, char **argv, char **envp, int fd) { 
     _cleanup_free_ char *local = NULL, *peer = NULL; 
     _cleanup_close_ int fd_accepted = -1; 

     fd_accepted = accept4(fd, NULL, NULL, 0); 
     if (fd_accepted < 0) 
       return log_error_errno(errno, "Failed to accept connection on fd:%d: %m", fd); 

     getsockname_pretty(fd_accepted, &local); 
     getpeername_pretty(fd_accepted, true, &peer); 
     log_info("Connection from %s to %s", strna(peer), strna(local)); 

     return fork_and_exec_process(name, argv, envp, fd_accepted); 
} 

наконец, itexecvpe(name, argv, envp); вызовы и завернуть ФД в envp. Существует трюк в нем, если fd_accepted не равна SD_LISTEN_FDS_START, его называют dup2() к маркам SD_LISTEN_FDS_START быть копией fd_accepted:

if (start_fd != SD_LISTEN_FDS_START) { 
      assert(n_fds == 1); 

      r = dup2(start_fd, SD_LISTEN_FDS_START); 
      if (r < 0) 
        return log_error_errno(errno, "Failed to dup connection: %m"); 

      safe_close(start_fd); 
      start_fd = SD_LISTEN_FDS_START; 
    } 

Таким образом, вы можете просто использовать дескриптор файла 3, как это в вашем приложении, sd_listen_fds будет разобрать переменные окружения LISTEN_FDS передается от envp:

int listen_sock; 
int fd_count = sd_listen_fds(0); 
if (fd_count == 1) { // assume one socket only 
    listen_sock = SD_LISTEN_FDS_START; // SD_LISTEN_FDS_START is a macro defined to 3 
} else { 
    // error 
} 
struct sockaddr addr; 
socklen_t addrlen; 
while (int client_sock = accept(listen_sock, &addr, &addrlen)) { 
    // do something 
} 
+0

Это ясно для меня, но то, что меня интересует это процесс прохождения дескриптора файла во время 'Exec()' без сотрудничества процесса выполняется. – j123b567

+0

@ j123b567 см. Редактирование. – jfly

+0

Благодарим вас за расширенный ответ. Я должен исследовать это немного. Для меня процессы все еще не связаны, но для меня есть два важных трюка. По умолчанию дескрипторы файлов остаются открытыми через 'execve()'. Это ново для меня. Второй трюк - это функция 'dup2()', которая делает окончательный переход fd. – j123b567

Смежные вопросы