阻塞性系统调用失败,errno(ENTIR)4 [Interrupted system call]系统调用被信号中断

1.阻塞与非阻塞

非阻塞:程序调用后,不管能不能立刻得到结果,当前进程都会直接返回。如果得到结果则返回成功,否则返回失败。

阻塞:程序调用后,如果不能立刻得到结果,则当前进程会被挂起,无限期等待,直到得到结果时才会返回。

系统调用一般可通过参数控制阻塞或者非阻塞。

常用在IPC通信和网络通信中,需要根据同步或异步设置阻塞和非阻塞:

msgsnd/msgrcv:消息队列发送、接收消息。

semop:信号量操作,用户改变信号量的值。P、V操作。

send/recv,read/write:socket 发送、读写缓冲区。

2.errno ENTIR

        errno ENTIR(4) 系统调用被信号中断,一般发生在被阻塞的系统调用中。

        在阻塞期间,被阻塞的进程收到了不可屏蔽的信号,操作系统会将信号写入该阻塞进程信号描述符,然后强行将进程状态从 TASK_INTERRUPTABLE 改变至 TASK_RUNNING,调用 schedule() 函数执行,由于进程之前一直被阻塞,而linux是交互型系统,因此,阻塞时间越长,进程动态优先级会被调高,因此该进程能在极短的时间内得到相应。但此时,系统调用需要完成的工作并没完成,提前返回将导致错误,设置 errno 为 EINTR。
 

3.解决办法

        在阻塞调用失败后,检查系统错误码 errno 是否是 ENTIR, 重复当前系统调用。

        msgsnd代码示例(msgsnd最后一个参数为0代表当消息队列满时,msgsnd将会阻塞,直到消息能写进消息队列):

...
while (1) {
    if (msgsnd( msqid, &sendbuf, sendlen, 0) < 0 && errno == ENTIR) {
        continue;
    }
    break;
}
...

参考true0face-系统调用中断。链接:https://blog.csdn.net/true0face/article/details/48132091 

"recv failed: Resource temporarily unavailable" 是一个常见的网络编程错误,通常在使用套接字(socket)进行数据接收时出现。这个错误表示接收操作失败,因为资源暂时不可用。具体原因和解决方法如下: 1. **非阻塞模式(Non-blocking Mode)**: - 当套接字被设置为非阻塞模式时,如果接收缓冲区中没有数据,`recv` 函数会立即返回这个错误。 - 解决方法:使用 `select` 或 `poll` 等多路复用机制来检查套接字是否可读。 2. **信号中断(Signal Interrupt)**: - `recv` 操作可能被信号中断,导致返回这个错误。 - 解决方法:在错误处理代码中检查 `errno` 是否为 `EINTR`,如果是,则重新调用 `recv`。 3. **缓冲区满**: - 接收缓冲区已满,无法接收更多数据。 - 解决方法:增加缓冲区大小或调整网络应用程序的流量控制策略。 4. **套接字关闭**: - 套接字可能已经被关闭,导致接收操作失败。 - 解决方法:在调用 `recv` 前检查套接字的有效性。 示例代码(使用非阻塞模式): ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main() { int sockfd; struct sockaddr_in server_addr; char buffer[1024]; int n; // 创建套接字 sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { perror("socket"); exit(1); } // 设置套接字为非阻塞模式 int flags = fcntl(sockfd, F_GETFL, 0); fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); // 连接服务器 server_addr.sin_family = AF_INET; server_addr.sin_port = htons(8080); server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { if (errno != EINPROGRESS) { perror("connect"); close(sockfd); exit(1); } } // 接收数据 n = recv(sockfd, buffer, sizeof(buffer), 0); if (n < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { printf("No data available\n"); } else if (errno == EINTR) { printf("Interrupted system call\n"); } else { perror("recv"); close(sockfd); exit(1); } } else if (n == 0) { printf("Connection closed\n"); } else { printf("Received data: %s\n", buffer); } close(sockfd); return 0; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值