Linux 阻塞非阻塞

linux open函数 在非阻塞模式下的使用

ChatGPT said:

在 Linux 中,open() 函数用于打开文件或设备。在**非阻塞模式(non-blocking mode)**下使用 open(),主要用于设备文件、FIFO、套接字等可能会导致阻塞的文件类型。常规的普通文件不会因为是否阻塞而行为不同。


一、使用方式

非阻塞模式的关键在于设置 O_NONBLOCK 标志。

示例代码:

复制代码

c

CopyEdit

#include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <errno.h> int main() { int fd = open("/dev/ttyS0", O_RDONLY | O_NONBLOCK); // 示例:打开串口设备为非阻塞读 if (fd == -1) { perror("open"); return 1; } char buffer[100]; ssize_t n = read(fd, buffer, sizeof(buffer)); if (n == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { printf("No data available now (non-blocking mode)\n"); } else { perror("read"); } } else if (n == 0) { printf("EOF reached\n"); } else { printf("Read %zd bytes\n", n); } close(fd); return 0; }


二、重点说明

  • O_NONBLOCK 是 fcntl.h 中定义的宏,用来设置文件描述符为非阻塞模式。

  • 对于普通文件(如磁盘上的文本文件),O_NONBLOCK 没有实际效果,read() 总是会返回所有可读数据。

  • 对于如下类型文件特别有用:

    • 管道(FIFO)

    • 套接字(socket)

    • 设备文件(如 /dev/tty*, /dev/null)

  • 如果你想在打开之后再设置非阻塞模式 ,可以使用 fcntl():

复制代码

c

CopyEdit

int flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK);


三、典型用途场景

  • 事件驱动编程(如 epoll/select/poll) :

    配合 O_NONBLOCK 和 I/O 多路复用机制使用,避免阻塞,提高系统响应能力。

  • 设备驱动/串口通信/异步I/O :

    读取设备数据时不阻塞主程序流程。

  • 服务端程序/并发服务器 :

    接收多个客户端连接,避免因单个阻塞操作卡死整个进程。


如果你有具体场景(比如管道、socket、串口等),我可以给出更详细的使用建议。

2/2

You said:

管道

ChatGPT said:

管道(pipe)在 Linux 下是一种常见的进程间通信(IPC)方式。管道的读写操作如果没有数据准备好,默认是阻塞的,也就是说:

  • 读端调用 read(),没有数据时会阻塞等待写入。

  • 写端调用 write(),管道缓冲区满时会阻塞等待空间。


管道的非阻塞模式使用

1. 打开或创建管道文件时加 O_NONBLOCK

  • 命名管道(FIFO) ,用 mkfifo() 创建后,可以用 open() 以非阻塞模式打开。

  • 匿名管道 是通过 pipe() 创建的文件描述符对,不能直接用 open(),但是可以用 fcntl() 设置非阻塞标志。


2. 示例代码:命名管道非阻塞读写

假设先用命令创建管道:

复制代码

bash

CopyEdit

mkfifo myfifo

然后在程序里:

复制代码

c

CopyEdit

#include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <errno.h> int main() { // 以非阻塞方式打开命名管道读端 int fd = open("myfifo", O_RDONLY | O_NONBLOCK); if (fd == -1) { perror("open"); return 1; } char buf[128]; ssize_t n = read(fd, buf, sizeof(buf)); if (n == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { printf("No data available now (non-blocking read)\n"); } else { perror("read"); } } else if (n == 0) { printf("Writer closed pipe (EOF)\n"); } else { printf("Read %zd bytes: %.*s\n", n, (int)n, buf); } close(fd); return 0; }


3. 匿名管道非阻塞设置

假设用 pipe() 创建匿名管道:

复制代码

c

CopyEdit

int pipefd[2]; pipe(pipefd); // pipefd[0] 是读端,pipefd[1] 是写端

设置非阻塞:

复制代码

c

CopyEdit

#include <fcntl.h> int flags = fcntl(pipefd[0], F_GETFL, 0); fcntl(pipefd[0], F_SETFL, flags | O_NONBLOCK); flags = fcntl(pipefd[1], F_GETFL, 0); fcntl(pipefd[1], F_SETFL, flags | O_NONBLOCK);

这样读写端都变成非阻塞模式,读端没有数据时 read() 返回 -1 并设置 errno=EAGAIN,写端写满时 write() 也会返回 -1 并设置 errno=EAGAIN。


4. 非阻塞管道常见行为

操作 数据状态 阻塞/非阻塞行为
读端读数据 管道无数据 阻塞模式:阻塞;非阻塞:返回 -1,errno=EAGAIN
读端读数据 有数据 返回数据量
写端写数据 管道缓冲区满 阻塞模式:阻塞;非阻塞:返回 -1,errno=EAGAIN
写端写数据 有空间 写入数据量

如果你想,我还可以帮你写一个完整的读写管道非阻塞demo。你需要吗?

You said:

需要

ChatGPT said:

明白!下面是一个简单的 匿名管道 的非阻塞读写演示程序。演示父进程写管道,子进程非阻塞读管道的情况。

复制代码

c

CopyEdit

#include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <stdlib.h> int set_nonblocking(int fd) { int flags = fcntl(fd, F_GETFL, 0); if (flags == -1) { perror("fcntl F_GETFL"); return -1; } if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { perror("fcntl F_SETFL"); return -1; } return 0; } int main() { int pipefd[2]; if (pipe(pipefd) == -1) { perror("pipe"); return 1; } pid_t pid = fork(); if (pid < 0) { perror("fork"); return 1; } else if (pid == 0) { // 子进程 - 读端 close(pipefd[1]); // 关闭写端 // 设置读端为非阻塞 if (set_nonblocking(pipefd[0]) == -1) { exit(1); } char buf[100]; while (1) { ssize_t n = read(pipefd[0], buf, sizeof(buf) - 1); if (n == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { printf("子进程:管道暂无数据,继续等待...\n"); sleep(1); continue; } else { perror("read"); break; } } else if (n == 0) { printf("子进程:管道写端关闭,结束读取\n"); break; } else { buf[n] = '\0'; printf("子进程:读取到数据: %s\n", buf); } } close(pipefd[0]); exit(0); } else { // 父进程 - 写端 close(pipefd[0]); // 关闭读端 const char *msg = "Hello from parent!\n"; for (int i = 0; i < 5; i++) { ssize_t n = write(pipefd[1], msg, strlen(msg)); if (n == -1) { perror("write"); break; } printf("父进程:写入数据: %s", msg); sleep(2); } close(pipefd[1]); // 关闭写端,通知子进程EOF wait(NULL); // 等待子进程结束 } return 0; }


说明:

  • 父进程写端写数据,每隔 2 秒写一次;

  • 子进程读端设置为非阻塞模式,read() 无数据时不会阻塞,而是返回 -1 并设置 errno = EAGAIN,这时子进程打印等待信息并继续轮询;

  • 父进程关闭写端后,子进程读端读到 0 字节,表示管道关闭,退出循环。


你可以把这个代码保存为 pipe_nonblock.c,用 gcc pipe_nonblock.c -o pipe_nonblock 编译,然后运行看效果。

需要我帮你讲解代码每个部分的细节吗?

You said:

需要

ChatGPT said:

好的,我来帮你详细讲解这个非阻塞管道读写程序的每个关键部分:


1. set_nonblocking 函数

复制代码

c

CopyEdit

int set_nonblocking(int fd) { int flags = fcntl(fd, F_GETFL, 0); if (flags == -1) { perror("fcntl F_GETFL"); return -1; } if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { perror("fcntl F_SETFL"); return -1; } return 0; }

  • 作用:给指定的文件描述符 fd 添加非阻塞标志 O_NONBLOCK。

  • fcntl(fd, F_GETFL, 0):获取当前文件描述符状态标志。

  • fcntl(fd, F_SETFL, flags | O_NONBLOCK):在原有标志基础上加上非阻塞标志。


2. 创建匿名管道

复制代码

c

CopyEdit

int pipefd[2]; if (pipe(pipefd) == -1) { perror("pipe"); return 1; }

  • pipefd[0] 是读端,pipefd[1] 是写端。

  • 管道是一对文件描述符,进程间通过它们传输数据。


3. 创建子进程

复制代码

c

CopyEdit

pid_t pid = fork(); if (pid < 0) { perror("fork"); return 1; } else if (pid == 0) { // 子进程 ... } else { // 父进程 ... }

  • fork() 复制当前进程,返回值用来区分父子进程。

4. 子进程处理(读端)

复制代码

c

CopyEdit

close(pipefd[1]); // 关闭写端 set_nonblocking(pipefd[0]); // 设置读端非阻塞 char buf[100]; while (1) { ssize_t n = read(pipefd[0], buf, sizeof(buf) - 1); if (n == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { printf("子进程:管道暂无数据,继续等待...\n"); sleep(1); // 等待一秒再尝试读,避免CPU空转 continue; } else { perror("read"); break; } } else if (n == 0) { printf("子进程:管道写端关闭,结束读取\n"); break; } else { buf[n] = '\0'; printf("子进程:读取到数据: %s\n", buf); } } close(pipefd[0]);

  • 关闭写端,因为子进程只读。

  • 通过 set_nonblocking 把读端设成非阻塞。

  • 调用 read() 读数据:

    • 如果返回 -1 并且 errno 是 EAGAIN/EWOULDBLOCK,说明当前没有数据,不阻塞,打印提示并继续轮询。

    • 返回 0 表示写端关闭,读端读到 EOF,退出循环。

    • 返回 >0,说明读到数据,打印出来。

  • 轮询读取的方式适合没有事件通知机制的简单示例,实际开发中可以结合 select、poll 或 epoll。


5. 父进程处理(写端)

复制代码

c

CopyEdit

close(pipefd[0]); // 关闭读端 const char *msg = "Hello from parent!\n"; for (int i = 0; i < 5; i++) { ssize_t n = write(pipefd[1], msg, strlen(msg)); if (n == -1) { perror("write"); break; } printf("父进程:写入数据: %s", msg); sleep(2); } close(pipefd[1]); // 关闭写端,通知子进程EOF wait(NULL); // 等待子进程结束

  • 关闭读端,父进程只写管道。

  • 每隔 2 秒写一次消息,一共写 5 次。

  • 关闭写端后,子进程读端会感知到 EOF。

  • wait(NULL) 等待子进程结束,避免僵尸进程。


6. 程序运行效果总结

  • 子进程因为非阻塞读,没有数据时不会阻塞,而是打印"暂无数据"继续轮询。

  • 父进程定时写入数据,子进程能立即读到并打印。

  • 父进程结束写入并关闭写端后,子进程检测到 EOF 并退出。


如果你想,我也可以帮你写一个基于 select 或 poll 的非阻塞管道事件监听版本,避免轮询浪费CPU资源。你感兴趣吗?

You said:

可以

ChatGPT said:

好的!下面给你一个基于 select() 的非阻塞匿名管道读写示例,避免子进程不停轮询,只有管道有数据时才读:

复制代码

c

CopyEdit

#include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <stdlib.h> #include <sys/select.h> #include <sys/wait.h> int set_nonblocking(int fd) { int flags = fcntl(fd, F_GETFL, 0); if (flags == -1) { perror("fcntl F_GETFL"); return -1; } if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { perror("fcntl F_SETFL"); return -1; } return 0; } int main() { int pipefd[2]; if (pipe(pipefd) == -1) { perror("pipe"); return 1; } pid_t pid = fork(); if (pid < 0) { perror("fork"); return 1; } else if (pid == 0) { // 子进程,读端 close(pipefd[1]); if (set_nonblocking(pipefd[0]) == -1) { exit(1); } char buf[100]; fd_set readfds; while (1) { FD_ZERO(&readfds); FD_SET(pipefd[0], &readfds); int ret = select(pipefd[0] + 1, &readfds, NULL, NULL, NULL); if (ret == -1) { perror("select"); break; } if (FD_ISSET(pipefd[0], &readfds)) { ssize_t n = read(pipefd[0], buf, sizeof(buf) - 1); if (n == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { // 理论上select返回就绪,这里不会出现这个情况 continue; } else { perror("read"); break; } } else if (n == 0) { printf("子进程:管道写端关闭,退出\n"); break; } else { buf[n] = '\0'; printf("子进程读取: %s", buf); } } } close(pipefd[0]); exit(0); } else { // 父进程,写端 close(pipefd[0]); const char *msg = "Hello from parent via select!\n"; for (int i = 0; i < 5; i++) { ssize_t n = write(pipefd[1], msg, strlen(msg)); if (n == -1) { perror("write"); break; } printf("父进程写入: %s", msg); sleep(2); } close(pipefd[1]); wait(NULL); } return 0; }


说明

  • select() 会阻塞等待管道变为可读,避免了轮询浪费 CPU。

  • 一旦管道有数据,select 返回,子进程读数据。

  • 写端关闭后,读端 read() 返回 0,子进程退出。

  • 子进程依然设置了非阻塞模式,配合 select 使用,保证读操作不会意外阻塞。


想试试吗?或者需要改成 poll / epoll 版本也可以跟我说!

You said:

需要

ChatGPT said:

好的,这里给你一个基于 poll() 的非阻塞管道读写示例。poll 和 select 类似,但更灵活,适合监听大量文件描述符。

复制代码

c

CopyEdit

#include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <stdlib.h> #include <poll.h> #include <sys/wait.h> int set_nonblocking(int fd) { int flags = fcntl(fd, F_GETFL, 0); if (flags == -1) { perror("fcntl F_GETFL"); return -1; } if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { perror("fcntl F_SETFL"); return -1; } return 0; } int main() { int pipefd[2]; if (pipe(pipefd) == -1) { perror("pipe"); return 1; } pid_t pid = fork(); if (pid < 0) { perror("fork"); return 1; } else if (pid == 0) { // 子进程,读端 close(pipefd[1]); if (set_nonblocking(pipefd[0]) == -1) { exit(1); } struct pollfd pfd; pfd.fd = pipefd[0]; pfd.events = POLLIN; char buf[100]; while (1) { int ret = poll(&pfd, 1, -1); // 阻塞等待 if (ret == -1) { perror("poll"); break; } if (pfd.revents & POLLIN) { ssize_t n = read(pipefd[0], buf, sizeof(buf) - 1); if (n == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { continue; } else { perror("read"); break; } } else if (n == 0) { printf("子进程:管道写端关闭,退出\n"); break; } else { buf[n] = '\0'; printf("子进程读取: %s", buf); } } } close(pipefd[0]); exit(0); } else { // 父进程,写端 close(pipefd[0]); const char *msg = "Hello from parent via poll!\n"; for (int i = 0; i < 5; i++) { ssize_t n = write(pipefd[1], msg, strlen(msg)); if (n == -1) { perror("write"); break; } printf("父进程写入: %s", msg); sleep(2); } close(pipefd[1]); wait(NULL); } return 0; }


说明

  • poll() 阻塞等待管道读端可读事件。

  • 有数据时读取,不阻塞。

  • 写端关闭,read() 返回 0,子进程退出。

  • 代码结构和 select() 版本类似,但 poll 用 struct pollfd 传递监控信息,更适合多文件描述符场景。


需要我帮你写一个 epoll 版本吗?或者帮你解释这个 poll 示例?

You said:

需要

ChatGPT said:

好嘞!下面是基于 epoll 的非阻塞匿名管道读写示例。

epoll 是 Linux 下更高效的多路复用机制,适合监听大量文件描述符,性能优于 select 和 poll。

复制代码

c

CopyEdit

#include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <stdlib.h> #include <sys/epoll.h> #include <sys/wait.h> int set_nonblocking(int fd) { int flags = fcntl(fd, F_GETFL, 0); if (flags == -1) { perror("fcntl F_GETFL"); return -1; } if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { perror("fcntl F_SETFL"); return -1; } return 0; } int main() { int pipefd[2]; if (pipe(pipefd) == -1) { perror("pipe"); return 1; } pid_t pid = fork(); if (pid < 0) { perror("fork"); return 1; } else if (pid == 0) { // 子进程,读端 close(pipefd[1]); if (set_nonblocking(pipefd[0]) == -1) { exit(1); } int epfd = epoll_create1(0); if (epfd == -1) { perror("epoll_create1"); exit(1); } struct epoll_event event; event.events = EPOLLIN; event.data.fd = pipefd[0]; if (epoll_ctl(epfd, EPOLL_CTL_ADD, pipefd[0], &event) == -1) { perror("epoll_ctl"); exit(1); } struct epoll_event events[10]; char buf[100]; while (1) { int nready = epoll_wait(epfd, events, 10, -1); if (nready == -1) { perror("epoll_wait"); break; } for (int i = 0; i < nready; i++) { if (events[i].data.fd == pipefd[0]) { if (events[i].events & EPOLLIN) { ssize_t n = read(pipefd[0], buf, sizeof(buf) - 1); if (n == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { continue; } else { perror("read"); goto cleanup; } } else if (n == 0) { printf("子进程:管道写端关闭,退出\n"); goto cleanup; } else { buf[n] = '\0'; printf("子进程读取: %s", buf); } } } } } cleanup: close(pipefd[0]); close(epfd); exit(0); } else { // 父进程,写端 close(pipefd[0]); const char *msg = "Hello from parent via epoll!\n"; for (int i = 0; i < 5; i++) { ssize_t n = write(pipefd[1], msg, strlen(msg)); if (n == -1) { perror("write"); break; } printf("父进程写入: %s", msg); sleep(2); } close(pipefd[1]); wait(NULL); } return 0; }


重点说明:

  • 用 epoll_create1() 创建 epoll 实例。

  • 用 epoll_ctl() 将管道读端添加到 epoll 监听列表,监听 EPOLLIN(可读事件)。

  • 用 epoll_wait() 阻塞等待事件发生,只有有数据可读时才返回。

  • 读取数据,EOF(read 返回 0)时退出。

  • 子进程的管道读端设置为非阻塞。

  • 父进程写端按周期写入数据,写完关闭。


你可以试试,觉得如何?

还想了解 epoll 细节,或者要帮你写基于 socket 的 epoll 示例也行。

You said:

接收和发送端可以同时用open打开并且设置为非阻塞模式吗?

ChatGPT said:

可以的!

在 Linux 下,管道的读端和写端确实可以分别用 open() 打开(或者创建后继承),并且都设置成非阻塞模式,这样读写操作就不会阻塞进程。


具体说明:

  • 管道本质上是文件描述符,和普通文件一样都能用 fcntl() 设置非阻塞标志 O_NONBLOCK。

  • 读端设置非阻塞时,read() 在无数据时不会阻塞,直接返回 -1,errno = EAGAIN 或 EWOULDBLOCK。

  • 写端设置非阻塞时,write() 在管道缓冲区满时不会阻塞,直接返回 -1,errno = EAGAIN。

  • 这对需要异步读写的程序很有用,比如事件驱动模型(使用 select / poll / epoll)。

  • 如果是通过文件(FIFO 命名管道)而非匿名管道,也可以用 open() 打开读写端,非阻塞方式同理。


举例:

复制代码

c

CopyEdit

int fd_read = open("fifo_pipe", O_RDONLY | O_NONBLOCK); int fd_write = open("fifo_pipe", O_WRONLY | O_NONBLOCK);

或者匿名管道后用 fcntl 设置:

复制代码

c

CopyEdit

fcntl(fd_read, F_SETFL, O_NONBLOCK); fcntl(fd_write, F_SETFL, O_NONBLOCK);


注意点:

  • 非阻塞写入时,如果管道缓冲区满,写操作会失败并返回 EAGAIN,这时一般要等到缓冲区有空再写,或者用 select/poll/epoll 监听写事件。

  • 非阻塞读取时,没有数据会立即返回,不阻塞。

  • 不能保证读写同时一定成功,应用层要处理这些边界情况。


总结:
接收端和发送端都可以同时以非阻塞模式打开管道并操作,这是完全支持且常用的。

如果你想,我可以帮你写一个基于命名管道(FIFO),读写端都非阻塞的示例程序。需要吗?

You said:

需要

ChatGPT said:

好的!下面给你一个基于**命名管道(FIFO)**的示例,接收端和发送端都用open()打开,并且都设置为非阻塞模式。


1. 创建命名管道(只需执行一次,或者放到程序外面)

复制代码

bash

CopyEdit

mkfifo /tmp/myfifo


2. 发送端程序(写端,非阻塞)

复制代码

c

CopyEdit

#include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <string.h> int main() { int fd = open("/tmp/myfifo", O_WRONLY | O_NONBLOCK); if (fd == -1) { perror("open fifo for write"); return 1; } const char *msg = "Hello from writer via FIFO\n"; for (int i = 0; i < 5; i++) { ssize_t n = write(fd, msg, strlen(msg)); if (n == -1) { if (errno == EAGAIN) { printf("写入缓冲区满,稍后重试...\n"); usleep(500000); // 0.5秒后重试 i--; // 重试这次写入 continue; } else { perror("write"); break; } } printf("写入数据: %s", msg); sleep(1); } close(fd); return 0; }


3. 接收端程序(读端,非阻塞)

复制代码

c

CopyEdit

#include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <string.h> int main() { int fd = open("/tmp/myfifo", O_RDONLY | O_NONBLOCK); if (fd == -1) { perror("open fifo for read"); return 1; } char buf[128]; while (1) { ssize_t n = read(fd, buf, sizeof(buf)-1); if (n == -1) { if (errno == EAGAIN) { printf("暂无数据,继续等待...\n"); usleep(500000); // 0.5秒 continue; } else { perror("read"); break; } } else if (n == 0) { printf("写端关闭,结束读取\n"); break; } else { buf[n] = '\0'; printf("读取数据: %s", buf); } } close(fd); return 0; }


使用说明:

  • 先确保执行过 mkfifo /tmp/myfifo,创建命名管道文件。

  • 分别在两个终端编译运行发送端和接收端程序。

  • 都用了 O_NONBLOCK,写端写缓冲区满会返回 EAGAIN,写端程序做了简单重试处理。

  • 读端没数据时也不会阻塞,会循环等待。


如果你需要,我也可以帮你写一个用 select 或 poll 监听命名管道可读可写事件的版本。你需要吗?

You said:

先确保执行过 mkfifo /tmp/myfifo,创建命名管道文件 是什么意思

ChatGPT said:

我说的"先确保执行过 mkfifo /tmp/myfifo,创建命名管道文件"意思是:

命名管道(FIFO)是一种特殊的文件,它像普通文件一样有路径(比如 /tmp/myfifo),但它是内核提供的管道通信机制。要使用命名管道,必须先创建这个特殊的文件。


怎么创建?

你需要在终端(命令行)执行:

复制代码

bash

CopyEdit

mkfifo /tmp/myfifo

这条命令会在 /tmp 目录下创建一个名叫 myfifo 的命名管道文件。


为什么要先创建?

  • 程序里用 open("/tmp/myfifo", ...) 打开这个文件。

  • 如果文件不存在,open() 会失败,程序无法正常运行。

  • 所以先用 mkfifo 命令创建它。


你可以这样操作:

  1. 打开一个终端,执行:

    复制代码

    bash

    CopyEdit

    mkfifo /tmp/myfifo

  2. 然后编译运行我之前给你的两个程序(读和写程序),它们会通过这个管道文件通信。


总结就是:

命名管道文件是内核的一种通信端点,要先用 mkfifo 创建,程序才能打开和使用它。


如果你想,我也可以帮你写个程序代码版本自动创建命名管道(用 mkfifo() 系统调用),你要吗?

相关推荐
沫璃染墨2 分钟前
《从零入门Linux系统篇(五十一):线程篇·四——pthread线程库详解:从线程创建到终止与分离》
linux·运维·服务器·开发语言·c++·系统架构·线程
YYRAN_ZZU4 分钟前
GMSL开发加解串配置介绍
linux·嵌入式硬件
墨家前任巨子13 分钟前
定时关机脚本
运维
云计算练习生13 分钟前
什么是上下文切换?进程切换时 CPU 到底在保存什么
linux·服务器·操作系统·进程切换
用户05101225729614 分钟前
RGA(二)——RK3588 的核拓扑与能力差异
linux·嵌入式
ESDWAN15 分钟前
企业组网后网络频繁掉线,常见故障排查指南
运维·网络·架构
用户05101225729616 分钟前
RGA(一)——基础知识
linux·嵌入式
qetfw20 分钟前
Debian 综合服务实训:Apache2、Samba、LDAP、vsftpd 与 OpenVPN
linux·服务器·debian
用户05101225729621 分钟前
RGA(三)——实宽高、虚宽高与对齐约束
linux·嵌入式
fastjson_30 分钟前
帆软看板 - 问题收集
linux·前端·javascript