最近在看libcontainer中nsexec.c的实现,看到init进程的parent与child、grandchild之间的双工通信使用了socketpair。socketpair的使用与fifo类似,在不具名的情况下可以实现父子进程间简单的信息交换。

系统调用

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int socketpair(int domain, int type, int protocol, int sv[2]);

使用示例

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdbool.h>
#include <sys/wait.h>

#define ERR_EXIT(msg) \
do{ \
perror(msg); \
exit(EXIT_FAILURE); \
}while(0)

enum sync_t {
PARENT_ACK = 0x41,
CHILD_ACK = 0x43,
};
int main(){
int sv[2];
if(socketpair(AF_LOCAL,SOCK_STREAM,0,sv) == -1){
ERR_EXIT("open socket pair error.");
}
pid_t cpid;
cpid = fork();
if(cpid == -1){
ERR_EXIT("fork child error.");
}
int syncfd;
if(cpid == 0){
syncfd = sv[1];
if(close(sv[0] < 0))
ERR_EXIT("child close useless fd error.");
bool complete = false;
while(!complete){
enum sync_t s;
read(syncfd,&s,sizeof(s));
if(s == PARENT_ACK){
s = CHILD_ACK;
write(syncfd,&s,sizeof(s));
complete = true;
}
}
printf("child sync finish.\n");
exit(EXIT_SUCCESS);
}else{
syncfd = sv[0];
if(close(sv[1] < 0)){
ERR_EXIT("parent close useless fd error.");
}
bool complete = false;
enum sync_t s;
s = PARENT_ACK;
write(syncfd,&s,sizeof(s));
while(!complete){
enum sync_t s;
read(syncfd,&s,sizeof(s));
if(s == CHILD_ACK){
complete = true;
}
}
printf("parent sync finish.\n");
waitpid(cpid,NULL,0);
}

exit(EXIT_SUCCESS);
}