- 用于创建文件描述符的函数,包括pipe、dup/dup2函数
-
用于读写数据的函数,包括readv/writev、sendfile、mmap/munmap、splice和tee函数。
- 用于控制I/O行为和属性的函数,包括fcntl函数。
1.Pipe函数
pipe函数用于创建一个管道
#include<unistd.h> int pipe(int fd[2]); //成功返回0 失败返回-1并设置 errno fd[0]负责写入 fd[1]从管道读取数据
//如果想实现双i昂的数据传输 应该使用两个管道 默认read write都是堵塞的
2.socketpair函数
#include<sys/types.h> #include<sys/socket.h> int socketpair(int domain,int type,int protocol,int fd[2]);
//成功返回0 失败返回-1并设置 errno
- socketpair前三个参数的含义与socket系统调用的三个参数相同 但domain只能使用UNIX本地域协议族AF_UNIX
- socketpair创建的这对文件描述符都是既可读又可写的
3.dup函数和dup2函数 (复制文件述符file_descriptor
#include<unistd.h> int dup(int file_descriptor); //dup函数创建一个新的文件描述符,该新文件描述符和原有文件描述符file_descriptor
指向相同的文件、管道或者网络连接。
int dup2(int file_descriptor_one,int file_descriptor_two); //dup2和dup类似,不过它将返回第一个不小于file_descriptor_two的整数值。
dup和dup2系统调用失败时返回-1并设置errno。
- 把标准输入重定向到一个文件,或者把标准输出重定
- 向到一个网络连接(比如CGI编程)
- CGI 服务器
// // Created by jignchu on 11/25/18. // #include <stdio.h> #include <sys/types.h> #include <arpa/inet.h> #include <sys/socket.h> #include <stdlib.h> #include <assert.h> #include <strings.h> #include <errno.h> #include <string.h> #include <unistd.h> int main(int argc ,char *argv[]){ if (argc < 2) { printf("userage:%s ip_address port number",argv[0]); return 1; } const char *ip = argv[1]; int port =atoi(argv[2]); //stdlib.h trim space convert string to int type struct sockaddr_in address; bzero(&address, sizeof(address)); address.sin_family = AF_INET; inet_pton(AF_INET,ip,&address.sin_addr); //ipv4 address network show address.sin_port = htons(port); int sock = socket(PF_INET,SOCK_STREAM,0); assert(sock>=0); int ret = bind(sock,(struct sockaddr*)&address, sizeof(address)); assert(ret!=-1); ret = listen(sock,5); assert(ret!=-1); struct sockaddr_in client; socklen_t client_addrlength = sizeof(client); int connfd = accept(sock,(struct sockaddr*)&client,&client_addrlength); if (connfd < 0) { printf("error is %d",errno); } else{ close(STDOUT_FILENO); dup(connfd); printf("abcd "); close(connfd); } close(sock); return 0; }
4.readv函数和writev函数
- readv函数将数据从文件描述符读到分散的内存块中,即分散读
- writev函数则将多块分散的内存数据一并写入文件描述符中,即集中写
#include<sys/uio.h> ssize_t readv(int fd,const struct iovec*vector,int count); ssize_t writev(int fd,const struct iovec*vector,int count);
fd参数是被操作的目标文件描述符。 vector参数的类型是iovec结构数组 count参数是vector数组的长度
readv和writev在成功时返回读出/写入fd的字节数,失败则返回-1

// // Created by jignchu on 11/25/18. // #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <stdbool.h> #include <libgen.h> #include <fcntl.h> #include <sys/stat.h> #include <unistd.h> #include <sys/uio.h> #include <stddef.h> #define BUFFER_SIZE 1024 static const char* status_line[2] = {"200 OK","500 Internal server error"}; int main(int argc, char *argv[]){ if (argc < 3) { printf("useage:%s ip_address port_number filename ",basename(argv[0])); return 1; } const char *ip = argv[1]; int port = atoi(argv[2]); const char *file_name = argv[3];// the third val is dst file struct sockaddr_in address; bzero(&address, sizeof(address)); address.sin_family=AF_INET; inet_pton(AF_INET,ip,&address.sin_addr); address.sin_port = htons(port); int sock = socket(AF_INET,SOCK_STREAM,0); assert(sock>0); int ret = bind(sock,(struct sockaddr*)&address, sizeof(address)); assert(ret!=-1); struct sockaddr_in client; socklen_t client_addrlength = sizeof(client); int connfd = accept(sock,(struct sockaddr*)&client,&client_addrlength); if (connfd < 0) { printf("error is %d ",errno); } else{ char header_buf[BUFFER_SIZE]; memset(header_buf,'