找回密码
 立即注册
查看: 354|回复: 0

[linux] Linux进程等待

[复制链接]

279

主题

0

回帖

964

积分

超级版主

积分
964
发表于 2024-5-28 17:45:34 | 显示全部楼层 |阅读模式
本帖最后由 Shaw0xyz 于 2024-5-28 17:47 编辑

linux 操作系统中,进程管理是一个重要的组成部分。进程等待是指一个进程在执行过程中需要等待某个事件的发生,比如等待某个文件的读写完成,等待某个信号的到来等。本文将深入探讨 Linux 中进程等待的概念、常见方法以及应用场景。


1. 进程等待的概念

进程等待是指一个进程在某种条件未满足时,进入等待状态,暂停执行,直到条件满足时再恢复执行。这种机制可以提高系统资源的利用率,避免进程无效地占用 CPU 时间。

2. 常见的进程等待方法

2.1 阻塞等待

阻塞等待是指进程主动放弃 CPU 使用权,进入阻塞状态,等待某个事件的发生。当事件发生时,内核将进程从阻塞状态唤醒,恢复执行。

2.1.1 使用 `sleep` 函数

`sleep` 函数使进程在指定的时间段内进入睡眠状态。


  1. #include <unistd.h>

  2. int main() {
  3.     sleep(5); // 进程将等待5秒
  4.     return 0;
  5. }
复制代码



2.1.2 使用 `read` 函数

`read` 函数在读取数据时,如果没有数据可读,进程将进入阻塞状态,直到有数据可读或发生错误。


  1. #include <unistd.h>
  2. #include <fcntl.h>
  3. #include <stdio.h>

  4. int main() {
  5.     int fd = open("test.txt", O_RDONLY);
  6.     char buffer[100];
  7.     read(fd, buffer, sizeof(buffer)); // 进程在读取数据时阻塞
  8.     close(fd);
  9.     return 0;
  10. }
复制代码



2.2 非阻塞等待

非阻塞等待是指进程在等待某个事件时,不放弃 CPU 使用权,而是不断地检查条件是否满足。如果条件不满足,进程继续执行其他任务。

2.2.1 使用 `O_NONBLOCK` 标志

在打开文件时使用 `O_NONBLOCK` 标志,可以使读写操作变为非阻塞模式。


  1. #include <unistd.h>
  2. #include <fcntl.h>
  3. #include <stdio.h>
  4. #include <errno.h>

  5. int main() {
  6.     int fd = open("test.txt", O_RDONLY | O_NONBLOCK);
  7.     char buffer[100];
  8.     int n = read(fd, buffer, sizeof(buffer));
  9.     if (n == -1 && errno == EAGAIN) {
  10.         printf("No data available\n");
  11.     }
  12.     close(fd);
  13.     return 0;
  14. }
复制代码



2.3 信号等待

信号等待是指进程在等待某个信号时进入等待状态,当信号到来时,内核唤醒进程,进程处理信号。

2.3.1 使用 `pause` 函数

`pause` 函数使进程进入睡眠状态,直到收到信号。


  1. #include <unistd.h>
  2. #include <signal.h>
  3. #include <stdio.h>

  4. void handler(int signum) {
  5.     printf("Signal received\n");
  6. }

  7. int main() {
  8.     signal(SIGINT, handler);
  9.     pause(); // 进程等待信号
  10.     return 0;
  11. }
复制代码



2.3.2 使用 `sigwait` 函数

`sigwait` 函数使进程在指定的信号集中等待信号。


  1. #include <signal.h>
  2. #include <stdio.h>

  3. int main() {
  4.     sigset_t set;
  5.     sigemptyset(&set);
  6.     sigaddset(&set, SIGINT);
  7.     sigprocmask(SIG_BLOCK, &set, NULL);

  8.     int signum;
  9.     sigwait(&set, &signum); // 进程等待信号
  10.     printf("Signal received: %d\n", signum);
  11.     return 0;
  12. }
复制代码


3. 应用场景

3.1 多进程编程

在多进程编程中,父进程可以使用 `wait` 或 `waitpid` 函数等待子进程的结束,以便获取子进程的退出状态。


  1. #include <sys/types.h>
  2. #include <sys/wait.h>
  3. #include <unistd.h>
  4. #include <stdio.h>

  5. int main() {
  6.     pid_t pid = fork();
  7.     if (pid == 0) {
  8.         // 子进程
  9.         sleep(2);
  10.         return 42;
  11.     } else {
  12.         // 父进程
  13.         int status;
  14.         waitpid(pid, &status, 0); // 父进程等待子进程结束
  15.         if (WIFEXITED(status)) {
  16.             printf("Child exited with status %d\n", WEXITSTATUS(status));
  17.         }
  18.     }
  19.     return 0;
  20. }
复制代码



3.2 网络编程

在网络编程中,服务器进程可以使用 `select` 或 `poll` 函数等待多个文件描述符的事件。


  1. #include <sys/select.h>
  2. #include <unistd.h>
  3. #include <stdio.h>

  4. int main() {
  5.     fd_set readfds;
  6.     FD_ZERO(&readfds);
  7.     FD_SET(STDIN_FILENO, &readfds);

  8.     int ret = select(STDIN_FILENO + 1, &readfds, NULL, NULL, NULL); // 等待输入
  9.     if (ret > 0 && FD_ISSET(STDIN_FILENO, &readfds)) {
  10.         char buffer[100];
  11.         read(STDIN_FILENO, buffer, sizeof(buffer));
  12.         printf("Input: %s\n", buffer);
  13.     }
  14.     return 0;
  15. }
复制代码


3.3 文件 I/O

在文件 I/O 操作中,进程可以使用 `epoll` 等机制等待文件描述符的事件,提高效率。


  1. #include <sys/epoll.h>
  2. #include <unistd.h>
  3. #include <fcntl.h>
  4. #include <stdio.h>

  5. int main() {
  6.     int epfd = epoll_create1(0);
  7.     struct epoll_event event;
  8.     event.events = EPOLLIN;
  9.     event.data.fd = STDIN_FILENO;
  10.     epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &event);

  11.     struct epoll_event events[10];
  12.     int nfds = epoll_wait(epfd, events, 10, -1); // 等待事件
  13.     if (nfds > 0) {
  14.         char buffer[100];
  15.         read(events[0].data.fd, buffer, sizeof(buffer));
  16.         printf("Input: %s\n", buffer);
  17.     }
  18.     close(epfd);
  19.     return 0;
  20. }
复制代码



4. 总结

本文详细介绍了 Linux 进程等待的概念、常见方法以及应用场景。通过掌握这些内容,可以在实际开发中合理地使用进程等待机制,提高程序的效率和响应速度。希望本文对您有所帮助。

荔枝学姐爱吃荔枝!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

联系站长|Archiver|手机版|小黑屋|主机论坛

GMT+8, 2025-4-5 02:38 , Processed in 0.061022 second(s), 24 queries .

Powered by 主机论坛 HostSsss.Com

HostSsss.Com

快速回复 返回顶部 返回列表