文件描述符,EXIT_FAILURE,memset()

本文深入探讨了文件描述符的概念及其在Unix/Linux系统中的应用,包括其生成方式、与标准输入输出的关系、与其他文件描述符的操作以及与文件加锁、套接字相关的一系列操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文件描述符是一个非负整数,实际上,他是一个索引值,指向内核为每一进程所维护的该进程打开文件的记录表。
当程序打开或创建一个文件时,内核向进程返回一个文件描述符。
仅使用于 Unix , Linux
标准输入文件描述符为0,标准输出为 1 ,标准错误为 2

POSIX 定义了 STDIN_FILENO、STDOUT_FILENO 和 STDERR_FILENO 来代替 0、1、2。这三个符号常量的定义位于头文件unistd.h

每个进程可以打开的文件的多少取决于系统内存的大小 及管理员的设定。

文件描述符与包括相关信息(如文件的打开模式、文件的位置类型、文件的初始类型等)的文件对象相关联,这些信息被称作文件的上下文。

进程获取文件描述符的方法:

~本机子例程open

~本机子例程create    (当用fork子进程创建文件时会获得其父进程所有文件描述符副本)  ,  这些在执行fork 时打开。

~从父进程继承   (允许访问父进程所使用的所有文件)

建议使用头文件中定义的三个宏来表示: STDIN_FILENO(标准输入) , STDOUT_FILENO (标准输出), STDERR_FILENO(标准错误)。


EXIT_FAILURE 可以作为exit()的参数来使用,表示没有成功地执行一个程序。

EXIT_SUCCESS 作为exit()的参数来使用,表示成功地执行一个程序


memset()函数原型

void *memset(void *s, int ch,size_t n);

将s所指向的内存中后n个字节用ch代替,然后返回指针s ,通常为新申请的内存做初始化,也是对较大型结构体或数组清零的最快方法。



文件描述符的生成

open(), open64(), creat(), creat64()

socket()

socketpair()

pipe()

与单一文件描述符相关的操作

read(), write()

recv(), send()

recvmsg(),sendmsg()

sendfile()

lseek(), lseek64()

fstat(),fstat64()

fchmod()

fchown()

与复数文件描述符相关的操作

select(), pselect()

poll()

与文件描述符表相关的操作

close()

dup()

dup2()

fcntl (F_DUPFD)

fcntl (F_GETFD and F_SETFD)

改变进程状态的操作

fchdir()

mmap()

与文件加锁的操作

flock()

fcntl (F_GETLK, F_SETLK and F_SETLKW)

lockf()

套接字相关的操作

connect()

bind()

listen()

accept()

getsockname()

getpeername()

getsockopt(), setsockopt()

shutdown(
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/time.h> #define MAX_CLIENTS 10 #define BUFFER_SIZE 1024 int main() { int server_fd, client_fd, max_fd; struct sockaddr_in server_addr, client_addr; socklen_t client_addr_len; fd_set readfds, temp_readfds; char buffer[BUFFER_SIZE]; int client_sockets[MAX_CLIENTS] = {0}; // 创建套接字 server_fd = socket(AF_INET, SOCK_STREAM, 0); if (server_fd < 0) { perror("socket creation failed"); exit(EXIT_FAILURE); } // 绑定地址和端口 memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(12345); if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } // 监听 if (listen(server_fd, MAX_CLIENTS) < 0) { perror("listen failed"); exit(EXIT_FAILURE); } // 初始化fd_set FD_ZERO(&readfds); FD_SET(server_fd, &readfds); max_fd = server_fd; while (1) { temp_readfds = readfds; // select等待就绪文件描述符 int activity = select(max_fd + 1, &temp_readfds, NULL, NULL, NULL); if (activity < 0) { perror("select failed"); exit(EXIT_FAILURE); } // 检查服务器套接字 if (FD_ISSET(server_fd, &temp_readfds)) { client_addr_len = sizeof(client_addr); client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_len); if (client_fd < 0) { perror("accept failed"); exit(EXIT_FAILURE); } printf("New client connected, socket fd is %d\n", client_fd); // 添加到客户端套接字数组 for (int i = 0; i < MAX_CLIENTS; i++) { if (clie
最新发布
03-14
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <sys/un.h> #define SOCKET_PATH "/tmp/udp_socket" //服务端bind的地址 #define SOCKET_clientPATH "/tmp/udp_socketclient" #define BUFFER_SIZE 1024 int main() { int sockfd; struct sockaddr_un server_addr, client_addr; char buffer[BUFFER_SIZE]; // 创建 UDP Unix 域套接字 sockfd = socket(AF_UNIX, SOCK_DGRAM, 0); if (sockfd == -1) { perror("socket 创建失败"); exit(EXIT_FAILURE); } // 设置服务器地址 memset(&server_addr, 0, sizeof(server_addr)); server_addr.sun_family = AF_UNIX; strncpy(server_addr.sun_path, SOCKET_PATH, sizeof(server_addr.sun_path) - 1); // 设置客户端地址 memset(&client_addr, 0, sizeof(client_addr)); client_addr.sun_family = AF_UNIX; strncpy(client_addr.sun_path, SOCKET_clientPATH, sizeof(client_addr.sun_path) - 1); unlink(SOCKET_clientPATH);//确保路径不存在 if (bind(sockfd, (struct sockaddr *)&client_addr, sizeof(client_addr))< 0 ) { perror("bind error"); close(sockfd); } // 客户端循环发送数据 while (1) { // 发送数据 char *message = "Hello, Server!"; if (sendto(sockfd, message, strlen(message), 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { perror("sendto 失败"); close(sockfd); exit(EXIT_FAILURE); } printf("客户端发送: %s\n", message); // 接收服务器响应 socklen_t addr_len = sizeof(client_addr); ssize_t recv_len = recvfrom(sockfd, buffer, BUFFER_SIZE, 0,NULL, NULL); if (recv_len == -1) { perror("recvfrom 失败"); close(sockfd); exit(EXIT_FAILURE); } buffer[recv_len] = '\0'; printf("客户端收到: %s\n", buffer); sleep(1); // 模拟间隔 } close(sockfd); return 0; } 解析一下,这样写对吗
03-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值