在linux中,一旦fork出子進程後,子進程就會繼承主進程的描述符,這為開發人員帶來了不少問題,比如當我使用socket的時候,一旦我綁定了某個連接埠,而後fork,如果此時fork出的子進程不退出的,那麼我主進程重啟後,就會出現無法綁定連接埠的問題。當然解決這種問題你可以選擇在socket初始化時,加入SOCK_CLOEXEC這個選項,使得子進程不繼承。那下面就介紹一種通用方法(如有問題,歡迎指出):
#include <stdlib.h>#include <stdio.h>#include <sys/types.h>#include <unistd.h>#include <signal.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/wait.h>#include <errno.h>void sigHandler(int signo){pid_t pid;int state;pid = wait(&state);printf("recvie child signal: [%d]\n", pid);}void restart_orig(){#ifndef _WIN32pid_t pid = vfork();if (pid < 0){printf("restart video error\n");return;}else if (pid == 0){for (int i = 0; i < sysconf(_SC_OPEN_MAX); i++){if (i != STDIN_FILENO && i != STDOUT_FILENO && i != STDERR_FILENO)close(i);}// 重啟相關進程//execlp("/bin/sh", "sh", "/mnt/mtd/setvideo.sh", "&", NULL);system("/bin/worker");exit(0);}else{int status = 0;pid_t wpid = wait(&status);printf("recvie child signal: [%d]\n", wpid);}#endifprintf("restart video\n");}int main(int agrc, char* agrv[]){//signal(SIGCHLD, sigHandler);int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);struct sockaddr_in saddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(1919);saddr.sin_addr.s_addr = inet_addr("127.0.0.1");bind(fd, (const sockaddr*)&saddr, sizeof(saddr));restart_orig();getchar();return 0;}