Linux技巧:如何等待多个进程完成
linux 等待 多个

首页 2025-01-10 09:12:15



Linux下等待多个任务或进程的高效策略 在Linux操作系统中,高效地管理和等待多个任务或进程的完成是系统编程和运维中的关键技能

    无论是在批处理脚本中处理多个后台作业,还是在复杂的并发编程场景中协调多个线程或进程,等待多个任务完成都是一项常见需求

    本文将深入探讨Linux环境下实现这一目标的多种方法和策略,帮助读者掌握高效且可靠的解决方案

     一、理解基础:进程与任务管理 在Linux系统中,进程是资源分配的基本单位,每个进程都拥有独立的内存空间和系统资源

    任务(task)通常指的是需要被系统调度执行的进程或线程

    在Linux中,管理进程和任务的工具有很多,如`ps`、`top`、`htop`等,这些工具能够帮助用户监控和查看系统中运行的进程状态

     对于等待多个进程完成的需求,最直接的方法是逐个检查每个进程的退出状态,但这显然不够高效,尤其是在处理大量进程时

    因此,我们需要更高级的机制来实现并行等待和同步

     二、使用Shell脚本等待多个后台作业 在Shell脚本中,可以使用`&`符号将命令放入后台执行,从而允许脚本继续执行其他任务

    然而,当需要等待这些后台作业完成时,可以使用`wait`命令

    对于多个后台作业,可以通过循环和数组来管理它们

     示例脚本: !/bin/bash 启动多个后台作业 job1=$({ sleep 5; echo Job 1 done;} &) job2=$( { sleep 3; echo Job 2 done; }& ) job3=$( { sleep 7; echo Job 3 done; }& ) 收集所有后台作业的PID pids=($!) 注意:这里只会捕捉到最后一个后台作业的PID,需要改进 修正PID收集方法 pids=() job_array=($job1 $job2 $job for jobin ${job_array【@】}; do pids+=($(echo $job |awk {print $1})) done 等待所有后台作业完成 for pidin ${pids【@】}; do wait $pid done echo All jobs completed. 注意:上述脚本中的PID收集方法存在缺陷,因为`$!`只能捕获最后一个后台命令的PID

    在实际应用中,可以通过将作业放入数组并单独记录每个作业的PID来改进

     三、使用GNU Parallel进行并行化 GNU Parallel是一个强大的Shell工具,用于在多个CPU核上并行执行作业

    它不仅能够简化并行任务的管理,还能自动处理作业依赖和负载均衡

     使用GNU Parallel等待多个任务完成: !/bin/bash 定义要执行的命令数组 commands=( sleep 5; echo Job 1 done sleep 3; echo Job 2 done sleep 7; echo Job 3 done ) 使用GNU Parallel并行执行命令,并等待所有命令完成 export -f my_command my_command(){ local cmd=$1 eval $cmd } export commands parallel my_command :::${commands【@】} echo All jobs completed by GNU Parallel. GNU Parallel通过内部机制管理作业的执行和同步,无需显式地等待每个作业完成,从而简化了脚本的编写

     四、使用系统V信号量或POSIX信号量进行进程间同步 对于更复杂的并发控制需求,系统V信号量(System V Semaphores)和POSIX信号量(POSIX Semaphores)提供了更为精细的同步机制

    这些机制允许进程在访问共享资源时进行互斥控制,从而避免资源冲突

     使用POSIX信号量示例: include include include include include defineNUM_THREADS 3 sem_t sem; void thread_func(void arg) { int id =(int)arg; printf(Thread %d: waiting to enter critical section... , id); sem_wait(&sem); printf(Thread %d: entered critical section , id); sleep(rand() % 5 + 1); // 模拟工作负载 printf(Thread %d: leaving critical section , id); sem_post(&sem); return NULL; } int main() { pthread_tthreads【NUM_THREADS】; intthread_ids【NUM_THREADS】; // 初始化信号量,初始值为1,表示允许一个线程进入临界区 sem_init(&sem, 0, 1); for(int i = 0; i < NUM_THREADS; i++) { thread_ids【i】 = i + 1;

MySQL连接就这么简单!本地远程、编程语言连接方法一网打尽
还在为MySQL日期计算头疼?这份加一天操作指南能解决90%问题
MySQL日志到底在哪里?Linux/Windows/macOS全平台查找方法在此
MySQL数据库管理工具全景评测:从Workbench到DBeaver的技术选型指南
MySQL密码忘了怎么办?这份重置指南能救急,Windows/Linux/Mac都适用
你的MySQL为什么经常卡死?可能是锁表在作怪!快速排查方法在此
MySQL单表卡爆怎么办?从策略到实战,一文掌握「分表」救命技巧
清空MySQL数据表千万别用错!DELETE和TRUNCATE这个区别可能导致重大事故
你的MySQL中文排序一团糟?记住这几点,轻松实现准确拼音排序!
别再混淆Hive和MySQL了!读懂它们的天壤之别,才算摸到大数据的门道