经典操作系统中进程状态图。
Linux内核里的进程状态
#define TASK_RUNNING 0
#define TASK_INTERRUPTIBLE 1
#define TASK_UNINTERRUPTIBLE 2
#define __TASK_STOPPED 4
#define __TASK_TRACED 8
/* in tsk->exit_state */
#define EXIT_DEAD 16
#define EXIT_ZOMBIE 32
TASK_RUNNING: 可执行的状态,但是不代表其正在运行。可能是在就绪队列中。所以在Linux中进程的就绪态和运行态是很模糊的,没有明确定义两个宏来表示。
TASK_INTERRUPTIBLE: 可中断睡眠状态。当进程等待某个资源时,进程会设置为TASK_INTERRUPTIBLE状态,当可用资源到来时,就设置为TASK_RUNNING状态。
TASK_UNINTERRUPTIBLE: 不可中断睡眠状态。当其他进程向其发送信号时,它是没有任何反应的。top、ps命令查看,其是D状态。
__TASK_STOPPED: 进程终止。
EXIT_DEAD: 进程消亡。
EXIT_ZOMBIE: 进程已经消亡了,但是task_struct结构体还没有释放。
进程状态设置
p->state = TASK_RUNNING;
建议使用Linux提供的API:
#define set_task_state(tsk, state_value) \ do { \ (tsk)->task_state_change = _THIS_IP_; \ set_mb((tsk)->state, (state_value)); \ } while (0) #define set_current_state(state_value) \ set_mb(current->state, (state_value))
进程标识符PID(Process Identifier): 用来识别进程的唯一号码。
PID的类型是一个int类型,所以默认最大值是32768。
为了循环使用PID编号,内核使用bitmap机制来管理当前已经分配的PID编号和空闲的PID编号。
getpid()系统调用返回当前进程的tgid值,而不是线程的pid值。
系统调用gettid()会返回线程的PID。
tgid和pid区别
posix标准规定:在一个线程组里面,必须使用相同的pid。
所以给一个组里面发送信号,组里的所有线程都能收到。
系统中第一个进程的名字有哪些
如何获取当前进程的task_struct数据结构?
简单的例子,用sp指针对齐8K,就可以获取struct task_struct结构体。
当前linux内核栈和task_struct之间的关系
为什么要把struct task_struct从 kernel stack中拧出来?
原因是struct thread_info大小是固定的,不会随着内核的发展而越来越大,但是struct task_struct结构体可能会越来越大,但是kernel 栈的空间确是固定的,所以留给内核栈的空间就比较多了。
linux内核中获取task_struct 的API,ARM64
register unsigned long current_stack_pointer asm ("sp");
static inline struct thread_info *current_thread_info(void)
{
return (struct thread_info *)
(current_stack_pointer & ~(THREAD_SIZE - 1));
}
#define get_current() (current_thread_info()->task)
#define current get_current()
task_struct和struct thread_info的关系