UNIX域协议之描述符传递
一、mycat程序
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h> #define BUFFSIZE 4096 int my_open(const char *, int);
void err_sys(const char *, ...);
void err_quit(const char *, ...); int main(int argc, char **argv)
{
int fd, n;
char buff[BUFFSIZE]; if (argc != ) {
err_quit("usage: mycat <pathname>");
} if ( (fd = my_open(argv[], O_RDONLY)) < ) {
err_sys("cannot open %s", argv[]);
} while ( (n = read(fd, buff, BUFFSIZE)) > ) {
write(STDOUT_FILENO, buff, n);
} exit();
}
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/socket.h> void err_sys(const char *, ...);
void err_quit(const char *, ...);
ssize_t Read_fd(int, void *, size_t, int *); int my_open(const char *pathname, int mode)
{
int fd, sockfd[], status;
pid_t childpid;
char c, argsockfd[], argmode[]; socketpair:
if (socketpair(AF_LOCAL, SOCK_STREAM, , sockfd) == -) {
if (errno == EINTR) {
goto socketpair;
} else {
err_quit("socketpair failed to create stream pipe");
}
} if ( (childpid = fork()) == ) { /* child process */
close(sockfd[]);
snprintf(argsockfd, sizeof(argsockfd), "%d", sockfd[]);
snprintf(argmode, sizeof(argmode), "%d", mode);
execl("../openfile/openfile", "openfile", argsockfd,
pathname, argmode,(char *) NULL);
err_sys("execl error");
} close(sockfd[]); /* close the end we don't use */ waitpid(childpid, &status, ); if (WIFEXITED(status) == ) {
err_quit("child did not terminate");
}
if ( (status = WEXITSTATUS(status)) == ) {
Read_fd(sockfd[], &c, , &fd);
} else {
errno = status; /* set errno value from child's status */
fd = -;
} close(sockfd[]);
return (fd);
}
#include <stddef.h>
#include <sys/socket.h> void err_sys(const char *, ...);
void err_quit(const char *, ...); ssize_t read_fd(int fd, void *ptr, size_t nbytes, int *recvfd)
{
struct msghdr msg;
struct iovec iov[];
ssize_t n; union {
struct cmsghdr cm;
char control[CMSG_SPACE(sizeof(int))];
} control_un;
struct cmsghdr *cmptr; msg.msg_control = control_un.control;
msg.msg_controllen = sizeof(control_un.control); msg.msg_name = NULL;
msg.msg_namelen = ; iov[].iov_base = ptr;
iov[].iov_len = nbytes;
msg.msg_iov = iov;
msg.msg_iovlen = ; if ( (n = recvmsg(fd, &msg, )) <= ) {
return (n);
} if ( (cmptr = CMSG_FIRSTHDR(&msg)) != NULL &&
cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {
if (cmptr->cmsg_level != SOL_SOCKET) {
err_quit("control level != SOL_SOCKET");
}
if (cmptr->cmsg_type != SCM_RIGHTS) {
err_quit("control type != SCM_RIGHTS");
}
*recvfd = *((int *) CMSG_DATA(cmptr));
} else {
*recvfd = -; /* descriptor was not passed */
} return(n);
} ssize_t Read_fd(int fd, void *ptr, size_t nbytes, int *recvfd)
{
ssize_t n; if ( (n = read_fd(fd, ptr, nbytes, recvfd)) < ) {
err_sys("read_fd error");
} return (n);
}
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h> /* ANSI C header file */
#include <syslog.h> /* for syslog() */ #define MAXLINE 4096 int daemon_proc; /* set nonzero by daemon_init() */ static void err_doit(int, int, const char *, va_list); /* Nonfatal error related to system call
* Print message and return */ void err_ret(const char *fmt, ...) { va_list ap; va_start(ap, fmt);
err_doit(, LOG_INFO, fmt, ap);
va_end(ap);
return;
} /* Fatal error related to system call
* Print message and terminate */ void err_sys(const char *fmt, ...) { va_list ap; va_start(ap, fmt);
err_doit(, LOG_ERR, fmt, ap);
va_end(ap);
exit();
} /* Fatal error related to system call
* Print message, dump core, and terminate */ void err_dump(const char *fmt, ...) {
va_list ap; va_start(ap, fmt);
err_doit(, LOG_ERR, fmt, ap);
va_end(ap);
abort(); /* dump core and terminate */
exit(); /* shouldn't get here */
} /* Nonfatal error unrelated to system call
* Print message and return */ void err_msg(const char *fmt, ...) { va_list ap; va_start(ap, fmt);
err_doit(, LOG_INFO, fmt, ap);
va_end(ap);
return;
} /* Fatal error unrelated to system call
* Print message and terminate */ void err_quit(const char *fmt, ...) { va_list ap; va_start(ap, fmt);
err_doit(, LOG_ERR, fmt, ap);
va_end(ap);
exit();
} /* Print message and return to caller
* Caller specifies "errnoflag" and "level" */ static void err_doit(int errnoflag, int level, const char *fmt, va_list ap) { int errno_save, n;
char buf[MAXLINE + ]; errno_save = errno; /* value caller might want printed */
#ifdef HAVE_VSNPRINTF
vsnprintf(buf, MAXLINE, fmt, ap); /* safe */
#else
vsprintf(buf, fmt, ap); /* not safe */
#endif
n = strlen(buf);
if (errnoflag)
snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save));
strcat(buf, "\n"); if (daemon_proc) {
syslog(level, buf);
} else {
fflush(stdout); /* in case stdout and stderr are the same */
fputs(buf, stderr);
fflush(stderr);
}
return;
}
二、openfile程序
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h> void err_quit(const char *, ...);
ssize_t Write_fd(int, void *, size_t, int); int main(int argc, char **argv)
{
int fd; if (argc != ) {
err_quit("openfile <sockfd> <filename> <mode>");
} if ( (fd = open(argv[], atoi(argv[]))) < ) {
exit( (errno > ) ? errno : );
} if (Write_fd(atoi(argv[]), "", , fd) < ) {
exit( (errno > ) ? errno : );
} exit();
}
#include <stddef.h>
#include <sys/socket.h> void err_sys(const char *, ...); ssize_t write_fd(int fd, void *ptr, size_t nbytes, int sendfd)
{
struct msghdr msg;
struct iovec iov[]; union {
struct cmsghdr cm;
char control[CMSG_SPACE(sizeof(int))];
} control_un;
struct cmsghdr *cmptr; msg.msg_control = control_un.control;
msg.msg_controllen = sizeof(control_un.control); cmptr = CMSG_FIRSTHDR(&msg);
cmptr->cmsg_len = CMSG_LEN(sizeof(int));
cmptr->cmsg_level = SOL_SOCKET;
cmptr->cmsg_type = SCM_RIGHTS;
*((int *) CMSG_DATA(cmptr)) = sendfd; msg.msg_name = NULL;
msg.msg_namelen = ; iov[].iov_base = ptr;
iov[].iov_len = nbytes;
msg.msg_iov = iov;
msg.msg_iovlen = ; return (sendmsg(fd, &msg, ));
} ssize_t Write_fd(int fd, void *ptr, size_t nbytes, int sendfd)
{
ssize_t n; if ( (n = write_fd(fd, ptr, nbytes, sendfd)) < ) {
err_sys("write_fd error");
} return (n);
}
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h> /* ANSI C header file */
#include <syslog.h> /* for syslog() */ #define MAXLINE 4096 int daemon_proc; /* set nonzero by daemon_init() */ static void err_doit(int, int, const char *, va_list); /* Nonfatal error related to system call
* Print message and return */ void err_ret(const char *fmt, ...) { va_list ap; va_start(ap, fmt);
err_doit(, LOG_INFO, fmt, ap);
va_end(ap);
return;
} /* Fatal error related to system call
* Print message and terminate */ void err_sys(const char *fmt, ...) { va_list ap; va_start(ap, fmt);
err_doit(, LOG_ERR, fmt, ap);
va_end(ap);
exit();
} /* Fatal error related to system call
* Print message, dump core, and terminate */ void err_dump(const char *fmt, ...) {
va_list ap; va_start(ap, fmt);
err_doit(, LOG_ERR, fmt, ap);
va_end(ap);
abort(); /* dump core and terminate */
exit(); /* shouldn't get here */
} /* Nonfatal error unrelated to system call
* Print message and return */ void err_msg(const char *fmt, ...) { va_list ap; va_start(ap, fmt);
err_doit(, LOG_INFO, fmt, ap);
va_end(ap);
return;
} /* Fatal error unrelated to system call
* Print message and terminate */ void err_quit(const char *fmt, ...) { va_list ap; va_start(ap, fmt);
err_doit(, LOG_ERR, fmt, ap);
va_end(ap);
exit();
} /* Print message and return to caller
* Caller specifies "errnoflag" and "level" */ static void err_doit(int errnoflag, int level, const char *fmt, va_list ap) { int errno_save, n;
char buf[MAXLINE + ]; errno_save = errno; /* value caller might want printed */
#ifdef HAVE_VSNPRINTF
vsnprintf(buf, MAXLINE, fmt, ap); /* safe */
#else
vsprintf(buf, fmt, ap); /* not safe */
#endif
n = strlen(buf);
if (errnoflag)
snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save));
strcat(buf, "\n"); if (daemon_proc) {
syslog(level, buf);
} else {
fflush(stdout); /* in case stdout and stderr are the same */
fputs(buf, stderr);
fflush(stderr);
}
return;
}
UNIX域协议之描述符传递的更多相关文章
- 《TCP-IP详解卷3:TCP 事务协议、HTTP、NNTP和UNIX域协议》【PDF】下载
TCP-IP详解卷3:TCP 事务协议.HTTP.NNTP和UNIX域协议>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062539 ...
- UNIX域协议(命名套接字)
这里主要介绍命名UNIX域套接字 1.什么是UNIX域套接字Unix域协议并不是一个实际的协议族,而是在单个主机上执行客户/服务通信的一种方式.是进程间通信(IPC)的一种方式.它提供了两类套接字:字 ...
- Socket编程实践(13) --UNIX域协议
UNIX域协议 UNIX域套接字与TCP相比, 在同一台主机上, UNIX域套接字更有效率, 几乎是TCP的两倍(由于UNIX域套接字不需要经过网络协议栈,不需要打包/拆包,计算校验和,维护序号和应答 ...
- UNP学习笔记(第十五章 UNIX域协议)
UNIX域协议是在单个主机上执行客户/服务器通信的一种方法 使用UNIX域套接字有以下3个理由: 1.UNIX域套接字往往比通信两端位于同一个主机的TCP套接字快出一倍 2.UNIX域套接字可用于在同 ...
- UNP学习 Unix域协议
Unix域协议并不是一个实际的协议族,它只是在同一台主机上进行客户-服务器通信时,使用与在不同主机上的客户和服务器间通信时相同的API的一种方法. 当客户和服务器在同一台主机上时,Unix域协议是这套 ...
- 《Unix 网络编程》15:Unix 域协议
Unix 域协议 ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ 本 ...
- UNIX网络编程读书笔记:UNIX域协议
概述 UNIX域协议并不是一个实际的协议族,而是在单个主机上执行客户/服务器通信的一种方法,所用API与在不同主机上执行客户/服务器通信所用的API(套接口API)相同.UNIX域协议可视为进程间通信 ...
- NDK开发之获得域和方法描述符
在NDK开发之调用方法和NDK开发之访问域两篇博客中,我们在获得域ID和方法ID时都需要一个叫做描述符的参数,那么在实际开发中我们怎么知道我们要调用的域或者方法的描述符呢? 一个简单的方法就是使用Ja ...
- UNIX域协议(无名套接字)
关于什么是UNIX域套接字可以参考:http://www.cnblogs.com/xcywt/p/8185597.html这里主要介绍非命名的UNIX域套接字的用法.1.socketpair函数先看m ...
随机推荐
- mongodb复制+分片集原理
----------------------------------------复制集---------------------------------------- 一.复制集概述: Mongodb ...
- hashtable 简单介绍
Hashtable 1 注意小写 table 2 常用方法 void clear() boolean contains(Object value) ...
- Django 数据库读写分离 分库分表
多个数据库 配置: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BA ...
- 闲谈2-sat问题
问题简介 在计算机科学中,布尔可满足性问题(有时称为命题可满足性问题,缩写为SATISFIABILITY或SAT)是确定是否存在满足给定布尔公式的解释的问题.换句话说,它询问给定布尔公式的变量是否可以 ...
- 【原创】谈谈线上CPU100%排查套路
引言 不知道在大家面试中,有没有遇到这个问题 生产服务器上部署了几个java程序,突然出现了CPU100%的异常告警,你如何定位出问题呢? 这个问题分为两版回答! 高调版 对不起,我是做研发的,这个问 ...
- 原创|1分钟搞定 Nginx 版本的平滑升级与回滚
Nginx无论是对于运维.开发.还是测试来说,都是日常工作需要掌握的一个知识点,之前也写过不少关于Nginx相关的文章: Nginx服务介绍与安装 Nginx服务配置文件介绍 Nginx配置虚拟主机 ...
- Linux操作系统计划任务
++++++++++++++++++++++++++++++++++++++++++++++++标题:Linux操作系统的计划任务内容:计划任务分为单次任务和周期性任务,周期任务分为系统级计划任务和用 ...
- JAVA基础知识回顾(面试资料)
关于数据库知识和面试:https://www.cnblogs.com/yanqb/p/9894943.html 关于数据库知识和面试:https://www.cnblogs.com/yanqb/p/1 ...
- git配置ssh秘钥(公钥以及私钥)
桌面版git, 本文以github为例,gitlab等其它托管平台一样操作 当我们将代码托管到远程平台(GitHub.gitlab等)时, 我们需要在本地使用git进行push/pull代码时,需要 ...
- MongoDB系列:五、MongoDB Driver使用正确的姿势连接复制集
MongoDB复制集(Replica Set)通过存储多份数据副本来保证数据的高可靠,通过自动的主备切换机制来保证服务的高可用.但需要注意的时,连接副本集的姿势如果不对,服务高可用将不复存在. 使用复 ...