LINUX中文件描述符传递
body, table{font-family: 微软雅黑; font-size: 10pt}
table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;}
th{border: 1px solid gray; padding: 4px; background-color: #DDD;}
td{border: 1px solid gray; padding: 4px;}
tr:nth-child(2n){background-color: #f8f8f8;}
进程间传递文件描述符
|
第一步:初始化socketpair类型描述符(管道,全双工) #include <sys/types.h> #include <sys/socket.h> int socketpair(int domain, int type, int protocol, int sv[2]); int fds[2]; //和无名管道不一样,无名管道只能用于父子进程之间,现在我们要用于网络; socketpair(AF_LOCAL,SOCK_STREAM,0,fds); //local,是因为控制信息只能在本地传 |
第二步:sendmsg发送描述符 ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); //内核控制信息传递接口,可以传递文件描述符 sockfd 即sockpair初始化的描述符 fds[1]; |
|
1).定义结构体 struct msghdr msg;
sendmsg 关键是初始化 msghdr结构体
|
|||
|
unsigned char *CMSG_DATA(struct cmsghdr *cmsg); //把结构体传进去,返回要写入信息的首地址(待会要里面放fd(一个整形数)),也就是最后一块空间的首地址,最后面/*...*/中要放的信息
size_t CMSG_LEN(size_t length); //得出变长结构体大小16字节(这个是针对我们后面例子,传描述符,我们自己算的),待会分配空间要用到(前面三个成员指针3*4,最后一个int型,一共16)
//这个接口的原理就是拿到我们要传递的参数的大小length,进去加上12,返回16
|
|||
|
首先定义 struct cmsghdr *cmsg 指针
cmsg_len 中存取cmsghdr结构体的长度,通过CMSG_LEN进行计算,我们传递的fd的大小为整型四个字节,所以
size_t CMSG_LEN(size_t length);
int len = CMSG_LEN(sizeof(int));(16字节)
然后为结构体申请空间:
|
|
#include<sys/uio.h>
ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
|
ssize_t writev(int fd, const struct iovec *iov, int iovcnt); //这个函数可以传多个结构体,第二个数要传的结构体指针,第三个是要传的结构体个数 |
| 第三步:recvmsg 接收文件描述符,接收的 msghdr 结构体初始化和 sendmsg 几乎完全一致,区别如下: ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags); //内核控制信息传递接口,可以接受文件描述符 fd = *fdptr; |
|
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/uio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
|
int main()
{
int fd=open("file1",O_RDWR);
char buf1[10]="hello ";
char buf2[10]="world\n";
struct iovec iov[2];
iov[0].iov_base=buf1;
iov[0].iov_len=strlen(buf1);
iov[1].iov_base=buf2;
iov[1].iov_len=strlen(buf2);
int ret=writev(fd ,iov,2); if(-1==ret) { perror("writev"); return -1; }
//如果fd没有被赋值打开的文件描述符,这里传参默认0;
}
|
| func.h | |||
|
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/uio.h>
|
void send_fd(int fds,int fd)
{
struct msghdr msg;
memset(&msg,0,sizeof(msg));
struct iovec iov[2];
char buf1[10]="hello";
char buf2[10]="world";
iov[0].iov_base=buf1;
iov[0].iov_len=5;
iov[1].iov_base=buf2;
iov[1].iov_len=5;
msg.msg_iov=iov;
msg.msg_iovlen=2;
struct cmsghdr* cmsg;
int len=CMSG_LEN(sizeof(int));
cmsg=(struct cmsghdr*)calloc(1,len);
cmsg->cmsg_len=len;
cmsg->cmsg_level=SOL_SOCKET;
cmsg->cmsg_type=SCM_RIGHTS;
*(int*)CMSG_DATA(cmsg)=fd;
msg.msg_control=cmsg;
msg.msg_controllen=len;
int ret=sendmsg(fds,&msg,0);
if(-1==ret)
{
perror("sendmsg");
return;
}
}
|
void recv_fd(int fds,int* pfd)
{
struct msghdr msg;
memset(&msg,0,sizeof(msg));
struct iovec iov[2];
char buf1[10]={0};
char buf2[10]={0};
iov[0].iov_base=buf1;
iov[0].iov_len=5;
iov[1].iov_base=buf2; //这里是收不到对端发来的数据的,但是必须要写
iov[1].iov_len=5;
msg.msg_iov=iov;
msg.msg_iovlen=2;
struct cmsghdr* cmsg;
int len=CMSG_LEN(sizeof(int));
cmsg=(struct cmsghdr*)calloc(1,len);
cmsg->cmsg_len=len;
cmsg->cmsg_level=SOL_SOCKET;
cmsg->cmsg_type=SCM_RIGHTS;
//后面两个可以不写的
msg.msg_control=cmsg;
msg.msg_controllen=len;
int ret=recvmsg(fds,&msg,0);
if(-1==ret)
{
perror("recvmsg");
return;
}
*pfd=*(int*)CMSG_DATA(cmsg);
}
|
#include "func.h"
int main()
{
int fds[2]; //全双工
//pipe(fds); //这个管道不是前面学的无名管道
int ret;
ret=socketpair(AF_LOCAL,SOCK_STREAM,0,fds);
if(-1==ret)
{
perror("socketpair");
return -1;
}
if(!fork())
{
close(fds[1]);
int fd;
recv_fd(fds[0],&fd);
printf("child fd=%d\n",fd);
char buf[10]={0};
read(fd,buf,sizeof(buf));
printf("buf=%s\n",buf);
close(fd);
exit(0);
}else{
close(fds[0]);
int fd=open("file",O_RDWR);
printf("parent fd=%d\n",fd);
send_fd(fds[1],fd);
close(fd); //发过去,关闭,引用计数降为1
wait(NULL);
return 0;
}
}
//fds[0]和fds[1]都具有读写属性,但是也要关闭一端,剩下的那一端都可以读或者写。
|
LINUX中文件描述符传递的更多相关文章
- Linux中文件描述符fd和文件指针flip的理解
转自:http://www.cnblogs.com/Jezze/archive/2011/12/23/2299861.html 简单归纳:fd只是一个整数,在open时产生.起到一个索引的作用,进程通 ...
- [转载] linux中文件描述符fd和文件指针flip的理解
转载自http://www.cnblogs.com/Jezze/archive/2011/12/23/2299861.html 简单归纳:fd只是一个整数,在open时产生.起到一个索引的作用,进程通 ...
- linux中文件描述符
:: # cat ping.txt PING baidu.com (() bytes of data. bytes from ttl= time=32.1 ms bytes from ttl= tim ...
- 对于Linux中文件描述符的疑问以及解决
问题 每次web服务器或者是几乎所有Linux服务器都需要对文件描述符进行调整,我使用ulimit -n来查看当前用户的最多能打开的文件,默认设置的是1024个,但是系统运行起来以及开启一些简单的 ...
- Linux下文件描述符
http://blog.csdn.net/kumu_linux/article/details/7877770 文件描述符是一个简单的整数,用以标明每一个被进程所打开的文件和socket.第一个打开的 ...
- linux 最大文件描述符fd
使用四种框架分别实现百万websocket常连接的服务器 著名的 C10K 问题提出的时候, 正是 2001 年.这篇文章可以说是高性能服务器开发的一个标志性文档,它讨论的就是单机为1万个连接提供服务 ...
- Linux Shell 文件描述符 及 stdin stdout stderr 重定向
Abstract: 1) Linux Shell 命令的标准输入.标准输出.标准错误,及其重定位: 2)Linux Shell 操作自定义文件描述符: 文件描述符是与文件相关联的一些整数,他们保持与已 ...
- linux 最大文件描述符
Linux对应用程序能打开的的最大文件描述符数量有两个层次的限制:用户级限制和系统级限制. 用户级限制是指目标用户运行的所有进程总共能打开的文件描述符数. 系统级的限制是指所有用户总共能打开的文件描述 ...
- 【详解】Linux的文件描述符fd与文件指针FILE*互相转换
使用系统调用的时候用文件描述符(file descriptor,简称fd)的时候比较多,但是操作比较原始.C库函数在I/O上提供了一些方便的包装(比如格式化I/O.重定向),但是对细节的控制不够. 如 ...
随机推荐
- iOS 总结APP间跳转的常用以及非常用需求 APP跳转Safari APP跳转APP
需求驱动技术,有了新的需求,旧技术无法实现时,就会有新的技术出现. 一般的APP跳转需求有以下几种: 1. 从自己的APP跳转到别人的APP. 2. 从自己的APP跳转系统APP. 3. 让别人的A ...
- windows下mysql安装失败的一个解决案例
操作系统:windows8.1,之前安装过mysql,这次安装在配置的最后一部执行“Apply security settings”的过程中弹出经典错误: Access denied for user ...
- ANE报错fix:Could not generate timestamp: Connection reset.
如果你打包ANE时候 报了:Could not generate timestamp: Connection reset. 那么很有可能你用了JDK 1.8. 解决方案一 退回到 JDK 1.7,重新 ...
- C/C++:函数的编译方式与调用约定以及extern “C”的使用
转自:https://www.cnblogs.com/qinfengxiaoyue/archive/2013/02/04/2891908.html 函数在C++编译方式与C编译方式下的主要不同在于:由 ...
- 机器学习与R语言:kNN
#---------------------------------------- # 功能描述:演示kNN建模过程 # 数据集:威斯康星乳腺癌诊断 # #---------------------- ...
- 一键安装lnmp(1)
#!/bin/bash#author:zhaocl#Software directory:$pathpath=`pwd`cd $path. $path/cacti.sh. $path/nginx.sh ...
- 20145303《Java程序设计》实验三实验报告
20145303<Java程序设计>实验三实验报告 ssh公钥配置及git安装: eclipse中git配置: 队友链接: http://www.cnblogs.com/5321z/p/5 ...
- 20145328 《Java程序设计》第8周学习总结
20145328 <Java程序设计>第8周学习总结 教材学习内容总结 第十四章 NIO与NIO2 NIO使用频道(channel)来衔接数据节点,对数据区的标记提供了clear(),re ...
- Linux入门之--Linux文件系统结构
对于每一个Linux学习者来说,了解Linux文件系统的目录结构,是学好Linux的至关重要的一步.,深入了解linux文件目录结构的标准和每个目录的详细功能,对于我们用好linux系统只管重要,下面 ...
- 如何使一个openwrt下的软件开机自启动
条件有三: 1.需要在软件包的Makefile中添加宏定义Package/$(package-name)/preinst和Package/$(package-name)/prerm define Pa ...