一、常见的进程状态与理解
在操作系统内部,有专门用来管理进程的结构体,叫做struct task_struct,也称作进程控制块(PCB),主要包含描述进程的相关信息,如进程用户、进程状态、进程优先级、文件描述符(记录当前进程打开的文件)、主要进程标识的进程号和父进程号:
进程号(PID: Process Identity Number):唯一的标识一个进程,用于区分系统中的各个进程并方便操作系统进行管理;
父进程号:(PPID:Parent Process ID):用于描述一个进程的直接父进程的标识符,每个进程在创建时都会由一个已有的进程(即父进程)生成,这样就形成了进程的层级结构。通过PPID,可以追踪进程的来源,并了解进程之间的关系。
在PCB中记录的进程状态,不过是一些整数,这个整数是多少就代表进程此时处于什么状态。在CPU执行进程时,通过找到进程的PCB,从而找到进程的代码和数据,进而去执行这个进程。下面列举了一些进程状态:
注意:没有+时,默认是后台进程
进程调度(进程状态切换)
进程创建后,进程进入就绪态,当CPU调度到此进程时进入运行态,当时间片用完时,此进程会进入就绪态,如果此进程正在执行一些IO操作(阻塞操作)会进入阻塞态,完成IO操作(阻塞结束)后又可进入就绪态,等待CPU的调度,当进程运行结束即进入结束态。
一、睡眠机制与唤醒机制
睡眠机制:
1)主动睡眠(Blocking Sleep): 进程自愿进入睡眠状态,通常是通过系统调用如sleep()、wait()等。
2)被动睡眠(Interruptible Sleep): 进程在等待某个条件满足(如I/O操作),可以被信号唤醒。
Linux通过内核提供的系统调用来控制进程的睡眠。常用的系统调用有:
sleep(): 使进程暂停指定的秒数。
usleep(): 使进程暂停指定的微秒数。
nanosleep(): 使进程暂停指定的纳秒数。
Tips:睡眠机制帮助节省CPU资源,尤其是在I/O密集型任务中;在可中断睡眠状态下,进程在收到信号时会被唤醒并处理信号。
唤醒机制
1)信号(Signal): 进程可以通过接受特定信号被唤醒。
2)条件变量(Condition Variable): 多线程编程中用于同步多个线程的工具,可以让一个线程在某些条件下睡眠并等待被唤醒。
Tips:唤醒机制可以通过信号、I/O事件和线程同步原语(如条件变量)来有效管理进程和线程的状态,更好地利用系统资源,提高程序的响应性与性能。
一、用法实例
1.进程睡眠示例:
使用 sleep() 函数让进程暂停执行一段时间
使用 usleep() 函数,使进程睡眠0.5秒,精确度更高
使用 nanosleep(),使进程睡眠1.5秒,可以精细控制时间
2.进程唤醒实例:
使用信号唤醒进程,进程直到接收到 SIGUSR1 信号被唤醒。
使用 select() 函数等待I/O,如果在5秒内没有输入,select() 会返回,以便进程被唤醒。若有输入,则进程也会被唤醒。
使用条件变量唤醒线程,子线程在条件变量上等待,直到主线程调用 pthread_cond_signal() 唤醒它。主线程在等待2秒后,设置条件并唤醒子线程。(已经描述到这里,线程一并提及一下)