【Linux笔记】Linux进程概念与进程状态

这篇具有很好参考价值的文章主要介绍了【Linux笔记】Linux进程概念与进程状态。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、什么是进程

1.1、进程的概念

进程的概念:

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。

通常在一些计算机或操作系统的书籍上也会这样告诉我们:进程是被加载到内存中的程序,或者运行起来的程序就叫做进程。

1.2、进程的描述

而进程再被加载到内存中后,操作系统就一定要对其进行管理,而在操作系统看来对程序的管理本质上就是对程序数据的管理,所以操作系统就会从这些程序中抽象出一些共有属性来构建出一个结构体,然后为每一个进程都创建一个这样的结构体对象。
然后操作系统对进程的管理就转化成了对这些结构体对象的管理了,在操作系统中,这个用于描述和组织进程的东西被称为 进程控制块——PCB。

而进程控制块在不同的操作系统中的结构和名称也可能不一样,具体到Linux操作系统中的进程控制块是task_struct,它是Linux内核中的一种数据结构,其包含的内如大致如下:

标示符: 描述本进程的唯一标示符,用来区别其他进程。
状态: 任务状态,退出代码,退出信号等。
优先级: 相对于其他进程的优先级。
程序计数器: 程序中即将被执行的下一条指令的地址。
内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
上下文数据: 进程执行时处理器的寄存器中的数据[
I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
其他信息

task_struct的源码肯定是非常复杂的,但没关系我们可以先了解一下。

我们可以来看看对应的task_struct的源码:

struct task_struct {
	/*
	 * 进程状态。
	 */
	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
	/*
	 * 进程的基本信息。
	 */
	struct thread_info *thread_info;
	atomic_t usage;
	unsigned long flags;	/* per process flags, defined below */
	unsigned long ptrace;

	int lock_depth;		/* Lock depth */

	/*
	 * 进行的动态优先权和静态优先权
	 */
	int prio, static_prio;
	/*
	 * 进程所在运行队列。每个优先级对应一个运行队列。
	 */
	struct list_head run_list;
	/*
	 * 指向当前运行队列的prio_array_t
	 */
	prio_array_t *array;

	/*
	 * 进程的平均睡眠时间
	 */
	unsigned long sleep_avg;
	/*
	 * timestamp:进程最近插入运行队列的时间。或涉及本进程的最近一次进程切换的时间
	 * last_ran:最近一次替换本进程的进程切换时间。
	 */
	unsigned long long timestamp, last_ran;
	/*
	 * 进程被唤醒时所使用的代码。
	 * 0:进程处于TASK_RUNNING状态。
	 * 1:进程处于TASK_INTERRUPTIBLE或者TASK_STOPPED状态,而且正在被系统调用服务例程或内核线程唤醒。
	 * 2:进程处于TASK_INTERRUPTIBLE或者TASK_STOPPED状态,而且正在被ISR或者可延迟函数唤醒。
	 * -1:表示从UNINTERRUPTIBLE状态被唤醒
	 */
	int activated;

	/*
	 * 进程的调度类型:sched_normal,sched_rr或者sched_fifo
	 */
	unsigned long policy;
	/*
	 * 能执行进程的CPU的位掩码
	 */
	cpumask_t cpus_allowed;
	/*
	 * time_slice:在进程的时间片中,还剩余的时钟节拍数。
	 * first_time_slice:如果进程肯定不会用完其时间片,就把该标志设置为1。
	 *
	 * Dagger-axe注:目的为加速子进程的返回,防止内存中进程过多。
	 */
	unsigned int time_slice, first_time_slice;

#ifdef CONFIG_SCHEDSTATS
	struct sched_info sched_info;
#endif

	/*
	 * 通过此链表把所有进程链接到一个双向链表中。
	 */
	struct list_head tasks;
	/*
	 * ptrace_list/ptrace_children forms the list of my children
	 * that were stolen by a ptracer.
	 */
	/*
	 * 链表的头。该链表包含所有被debugger程序跟踪的P的子进程。
	 */
	struct list_head ptrace_children;
	/*
	 * 指向所跟踪进程的实际父进程链表的前一个下一个元素。
	 */
	struct list_head ptrace_list;

	/*
	 * mm:指向内存区描述符的指针
	 */
	struct mm_struct *mm, *active_mm;

/* task state */
	struct linux_binfmt *binfmt;
	long exit_state;
	int exit_code, exit_signal;
	int pdeath_signal;  /*  The signal sent when the parent dies  */
	unsigned long personality;
	/*
	 * 进程发出execve系统调用的次数。
	 */
	unsigned did_exec:1;
	/*
	 * 进程PID
	 */
	pid_t pid;
	/*
	 * 线程组领头线程的PID。
	 */
	pid_t tgid;
	/* 
	 * pointers to (original) parent process, youngest child, younger sibling,
	 * older sibling, respectively.  (p->father can be replaced with 
	 * p->parent->pid)
	 */
	/*
	 * 指向创建进程的进程的描述符。
	 * 如果进程的父进程不再存在,就指向进程1的描述符。
	 * 因此,如果用户运行一个后台进程而且退出了shell,后台进程就会成为init的子进程。
	 */
	struct task_struct *real_parent; /* real parent process (when being debugged) */
	/*
	 * 指向进程的当前父进程。这种进程的子进程终止时,必须向父进程发信号。
	 * 它的值通常与real_parent一致。
	 * 但偶尔也可以不同。例如:当另一个进程发出监控进程的ptrace系统调用请求时。
	 */
	struct task_struct *parent;	/* parent process */
	/*
	 * children/sibling forms the list of my children plus the
	 * tasks I'm ptracing.
	 */
	/*
	 * 链表头部。链表指向的所有元素都是进程创建的子进程。
	 */
	struct list_head children;	/* list of my children */
	/*
	 * 指向兄弟进程链表的下一个元素或前一个元素的指针。
	 */
	struct list_head sibling;	/* linkage in my parent's children list */
	/*
	 * P所在进程组的领头进程的描述符指针。
	 */
	struct task_struct *group_leader;	/* threadgroup leader */

	/* PID/PID hash table linkage. */
	/*
	 * PID散列表。通过这四个表,可以方便的查找同一线程组的其他线程,同一会话的其他进程等等。
	 */
	struct pid pids[PIDTYPE_MAX];

	struct completion *vfork_done;		/* for vfork() */
	/*
	 * 子进程在用户态的地址。这些用户态地址的值将被设置或者清除。
	 * 在do_fork时记录这些地址,稍后再设置或者清除它们的值。
	 */
	int __user *set_child_tid;		/* CLONE_CHILD_SETTID */
	int __user *clear_child_tid;		/* CLONE_CHILD_CLEARTID */

	/*
	 * 进程的实时优先级。
	 */
	unsigned long rt_priority;
	/*
	 * 以下三对值用于用户态的定时器。当定时器到期时,会向用户态进程发送信号。
	 * 每一对值分别存放了两个信号之间以节拍为单位的间隔,及定时器的当前值。
	 */
	unsigned long it_real_value, it_real_incr;
	cputime_t it_virt_value, it_virt_incr;
	cputime_t it_prof_value, it_prof_incr;
	/*
	 * 每个进程的动态定时器。用于实现ITIMER_REAL类型的间隔定时器。
	 * 由settimer系统调用初始化。
	 */
	struct timer_list real_timer;
	/*
	 * 进程在用户态和内核态下经过的节拍数
	 */
	cputime_t utime, stime;
	unsigned long nvcsw, nivcsw; /* context switch counts */
	struct timespec start_time;
/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
	unsigned long min_flt, maj_flt;
/* process credentials */
	uid_t uid,euid,suid,fsuid;
	gid_t gid,egid,sgid,fsgid;
	struct group_info *group_info;
	kernel_cap_t   cap_effective, cap_inheritable, cap_permitted;
	unsigned keep_capabilities:1;
	struct user_struct *user;
#ifdef CONFIG_KEYS
	struct key *session_keyring;	/* keyring inherited over fork */
	struct key *process_keyring;	/* keyring private to this process (CLONE_THREAD) */
	struct key *thread_keyring;	/* keyring private to this thread */
#endif
	int oomkilladj; /* OOM kill score adjustment (bit shift). */
	char comm[TASK_COMM_LEN];
/* file system info */
	/*
	 * 文件系统在查找路径时使用,避免符号链接查找深度过深,导致死循环。
	 * link_count是__do_follow_link递归调用的层次。
	 * total_link_count调用__do_follow_link的总次数。
	 */
	int link_count, total_link_count;
/* ipc stuff */
	struct sysv_sem sysvsem;
/* CPU-specific state of this task */
	struct thread_struct thread;
/* filesystem information */
	/*
	 * 与文件系统相关的信息。如当前目录。
	 */
	struct fs_struct *fs;
/* open file information */
	/*
	 * 指向文件描述符的指针
	 */
	struct files_struct *files;
/* namespace */
	struct namespace *namespace;
/* signal handlers */
	/*
	 * 指向进程的信号描述符的指针
	 */
	struct signal_struct *signal;
	/*
	 * 指向进程的信号处理程序描述符的指针
	 */
	struct sighand_struct *sighand;

	/*
	 * blocked:被阻塞的信号的掩码
	 * real_blocked:被阻塞信号的临时掩码(由rt_sigtimedwait系统调用使用)
	 */
	sigset_t blocked, real_blocked;
	/*
	 * 存放私有挂起信号的数据结构
	 */
	struct sigpending pending;

	/*
	 * 信号处理程序备用堆栈的地址
	 */
	unsigned long sas_ss_sp;
	/*
	 * 信号处理程序备用堆栈的大小
	 */
	size_t sas_ss_size;
	/*
	 * 指向一个函数的指针,设备驱动程序使用这个函数阻塞进程的某些信号
	 */
	int (*notifier)(void *priv);
	/*
	 * 指向notifier函数可能使用的数据
	 */
	void *notifier_data;
	sigset_t *notifier_mask;
	
	void *security;
	struct audit_context *audit_context;

/* Thread group tracking */
   	u32 parent_exec_id;
   	u32 self_exec_id;
/* Protection of (de-)allocation: mm, files, fs, tty, keyrings */
	spinlock_t alloc_lock;
/* Protection of proc_dentry: nesting proc_lock, dcache_lock, write_lock_irq(&tasklist_lock); */
	spinlock_t proc_lock;
/* context-switch lock */
	spinlock_t switch_lock;

/* journalling filesystem info */
	/*
	 * 当前活动日志操作处理的地址。
	 * 正在使用的原子操作对象。
	 */
	void *journal_info;

/* VM state */
	struct reclaim_state *reclaim_state;

	struct dentry *proc_dentry;
	struct backing_dev_info *backing_dev_info;

	struct io_context *io_context;

	unsigned long ptrace_message;
	siginfo_t *last_siginfo; /* For ptrace use.  */
/*
 * current io wait handle: wait queue entry to use for io waits
 * If this thread is processing aio, this points at the waitqueue
 * inside the currently handled kiocb. It may be NULL (i.e. default
 * to a stack based synchronous wait) if its doing sync IO.
 */
	wait_queue_t *io_wait;
/* i/o counters(bytes read/written, #syscalls */
	u64 rchar, wchar, syscr, syscw;
#if defined(CONFIG_BSD_PROCESS_ACCT)
	u64 acct_rss_mem1;	/* accumulated rss usage */
	u64 acct_vm_mem1;	/* accumulated virtual memory usage */
	clock_t acct_stimexpd;	/* clock_t-converted stime since last update */
#endif
#ifdef CONFIG_NUMA
  	struct mempolicy *mempolicy;
	short il_next;
#endif
};

二、关于进程的一些基本操作

2.1、查看进程

查看进程有很多种方式,我们今天主要看两种。
第一种:使用ps axj配合grep和管道来查看指定进程。
比如我们现在有一段这样的C程序:

#include <stdio.h>
#include <unistd.h>
 
int main() {                                                                                                                                                                                                 
   while (1) {
     printf("我是一个进程,我正在努力的跑!!\n");
     sleep(1);
   }
   return 0;
}

我们知道当它在内存中运行的时候,就变成了一个进程,所以我们先让它一直运行着:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
然后我们可以再复制一个SSH渠道去监视它:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
第二种方法:在 “/proc” 系统文件夹中查看所有进程:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
但是这里所显示的进程都是以进程的id命名的,所以我们可以先查出进程的id再去寻找:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
其中加上head -1这个指令表示的是显示第一行的信息,即头部信息。

2.2、杀进程

向上述一样,我们启动了一个死循环的进程,他一直在命令行中打印内容。那我们怎么技术它呢?
第一个方法就是在命令行中按下ctrl + c组合键:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
还有一种方法就是在另一个终端中,使用kill命令指定-9选项再加上进程id来结束:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言

2.3、获取进程id

我们刚才一直提到进程的id,那它有什么用呢?我们是否可以在代码中获取到对应进程的id呢?
关于进程的id(pid)有什么用我们下面再介绍,我们先来介绍怎样在进程中获取对应进程的pid。
我们可以使用操作系统为我们提供的系统调用 getpid()和getppid() 来获取进程及其父进程的id:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
关于getpidd()和getppid()的返回值,它其实是一个,名为pid_t的类型。我们平时使用仅需要将他看成是int类型即可,打印时也可以使用%d.

2.4、创建进程

我们可以使用系统调用接口fork()创建子进程:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
大家可能看到这样的结果会感到疑惑,为什么子进程的代码会执行了两次,而且看pid会发现有一次还是父进程执行的。
其实fork这样使用是不对的,想要正确的使用我们得先看看fork的使用手册:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
这个接口
“有两个返回值”
,如果创建成功那子进程的pid将返回给父进程,0将返回给子进程,如果创建失败则返回-1。
至于为什么一个函数会有两个返回值,这是一个非常复杂的问题,这需要我们以后再洗洗探讨,我们现在先知道有这么个现象即可。
而fork正确的使用方法是通过fork的返回值对父子进程进行“分流”,即父子进程执行不同的代码。
很简单,我们可以通过判断getpid的返回值来完成:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
从结果可以看出,进程不仅仅行了分流,而且默认是父进程先执行。

三、进程状态

我们知道操作系统对进程的管理本质上就是对进程控制块PCB的管理,而进程状态其实就是PCB内部的一个整型变量,根据不同的整型值来标识进程不同的状态。

3.1、普适操作系统中的进程状态

在很多将操作系统的书上都是将进程的状态分为如下几种:运行、挂起、阻塞、新建、就绪、等待、挂机、死亡。
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
而各种教材上面的各种状态的对应的名称也可能不一样,但是他们想要表达的意思是一样的。
其实只要是操作系统,他们的内核都大差不差,只是有些细微的地方不一样而已。

3.2、具体到Linux操作系统中的进程状态

而具体到Linux操作系统,进程的主要状态有以下六种:

R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。
D磁盘休眠状态(Disk sleep): 有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
X死亡状态(dead): 这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
僵死状态(Zombies): 是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后面讲)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程
僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态

而这些状态,在内核中其实是对应着一个任务状态数组,这实际上是一个字符数组,我们为此可以猜测出,进程的状态其实也是根据这个字符数组中对应的字符来标识的:

/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};

运行状态:
运行状态其实很好理解,只要一个进程正在运行(即进程的PCB位于CPU的运行队列中):
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
因为进程一直对a进行+1操作,所以它一直会处于运行状态。
注意: 如果你想进行测试,是一个进程一直处于运行状态,注意一定不使用printf()函数(比如死循环打印),因为这涉及到了io资源的申请,会让进程处于另一个状态:睡眠状态,这个下面会详细讲到。
睡眠状态
睡眠状态其实就是普适操作系统中的阻塞状态,因为进程需要等待某种资源:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
但是有的朋友可能会不解了,这里看到的今晨不是一直在运行着吗,为什么就是睡眠状态呢?
这是因为我们cpu的速度是非常快的,我们人是根本感知不到的,printf需要等待显示器的资源,我们人虽然看到的是屏幕上飞速的打印着,但是在cpu看来就是它等待了很久才能打印一次,所以我们的这个进程其实大部分时间都在等待资源,所以也就是睡眠状态。
深度睡眠状态
这个状态就没办法给大家演示了,因为这是个非常危险的状态,只有在内存空间严重不足时才会出现。如果系统出现了深度睡眠状态,那这个系统也即将崩溃了。而我们想演示也是没有办法做到的,因为它只能通过操作系统来到达。

当操作系统出现空间严重不足时,操作系统会将某些进程直接杀掉来保证系统能够正常运行,而有些进程是非常重要的,如果直接杀掉的话就会造成巨大的损失,这时候操作系统就会讲这些非常重要的进程转换到深度睡眠状态,其做法就是将这个进程的数据写入磁盘,所以这个状态也称为磁盘休眠状态。

处于深度睡眠状态的进程既不能被用户杀掉也不能被操作系统杀掉,只能通过断电或者等待进程自己醒来

暂停状态
在进程中有很多的“信号”,使用这些信号也可以将我们的进程设置成指定的状态,我们可以使用kill -l指令来查看系统信号的详细列表:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
我们今天主要看的是19这个信号,它的作用就是将一个进程设置成暂停状态:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
如果我们想让这个进程恢复运行,可以使用-18选项:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
死亡状态
死亡状态代表着一个进程已经完全结束,进程的PCB和代码数据全部被操作系统回收。
僵尸状态
我们的进程是为了帮助我们完成某种任务,而既然是完成任务,那进程在结束钱就应该返回任务执行的结果,供父进程或操作系统读取。

所以一个进程在退出的时候,并不能直接释放全部资源,对于进程的代码和数据,操作系统可以释放,因为该进程已经不会被执行了,但是该进程的PCB应该被保留,因为PCB中存放着该进程的各种状态代码,特别是退出状态码。

而僵尸状态就是进程在退出时等待父进程或操作系统来读取退出状态码,然后释放PCB的一种状态。

四、僵尸进程和孤儿进程

4.1、僵尸进程

上面我们提到一个进程在全部释放之前需要父进程或操作系统来读取进程的退出状态代码,而如果父进程一直读取子进程的退出状态码,那子进程的PCB将一直得不到释放,此时该进程就变成僵尸进程:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
我们设计这样一个程序,让子进程只执行5次,然后让子进程退出,让父进程一直在执行:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言

然后我们在查看对应的子进程就会发现子进程已经变成了僵尸进程了:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
这是因为虽然子进程退出了,但是父进程一直在执行,并不能读取子进程的退出码。

4.2、孤儿进程

孤儿进程是指父进程提前退出后,子进程被操作系统领养的一种情况,被操作系统领养的进程就被称为孤儿进程:
我们只需要将之前的代码改成让父进程先退出,然后子进程一直执行就可以模拟出孤儿进程了:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言

五、进程的优先级

进程的优先级与权限不同,权限是限制那些事情能做安歇事情不能做,而优先级则是规定那些事情先做那些事情后做。

因为CPU的资源是有限的,所以肯定不可能让所有进程都同时运行。所以规定哪个进程先运行哪个进程后运行也就变得至关重要了。所以操作系统就要为不同的进程设置不同的优先级。进程的优先级就是一个整型数字,这个数字越大则优先级越低,数字越小则优先级越高。

5.1、查看进程的优先级

我们可以使用ps -la指令来查看系统内的进程优先级:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
其中这个PRI标题就是进程的优先级,它其实就是英文priority的缩写。而Linux中进程的优先级范围为60-99,Linux中默认的进程优先级为80。

5.2、怎样修改进程的优先级

Linux支持动态的优先级调整,单兵不允许我们直接的修改进程的优先级,我们只能通过修改进程PCB中的一个nice值来间接的修改优先级,而这里的NI就是进程对应的nice值:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
进程的优先级的计算方式:

pri(新) = pri(老) + nice

因为nice的默认值为0,所以进程的默认优先级也就为80了,所以我们可以通过修改nice值来达到修改优先级的目的,修改nice值的其中一个方法的步骤为:

输入top --> 输入r --> 输入进程id --> 输入NI值

【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
而我们若想把优先级调高就需要root权限:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
而既然Linux已经规定了进程的优先级范围是60-99那也就说明了我们并不能随意地修改进程的优先级,间接的也就不能随意的修改nice值。
通过计算我们得出,规定了进程的优先级范围是60-99那nice值的范围也就是[-20 - 19]:
如果我们修改的范围超过了这个区间,那系统就会把nice只修改为边界情况:
【Linux笔记】Linux进程概念与进程状态,Linux操作系统,linux,笔记,c语言
注:公式 “pri(新) = pri(老) + nice” 中的老优先级每一次都是默认优先级80。文章来源地址https://www.toymoban.com/news/detail-740842.html

到了这里,关于【Linux笔记】Linux进程概念与进程状态的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Linux】进程概念(冯诺依曼体系结构、操作系统、进程)-- 详解

    1、概念 (1)什么是冯诺伊曼体系结构? 数学家冯·诺伊曼于 1946 年提出存储程序原理,把程序本身当作数据来对待,程序和该程序处理的数据用同样的方式储存。 冯·诺伊曼理论的要点是:计算机的数制采用二进制逻辑;计算机应该按照程序顺序执行。人们把冯·诺伊曼的

    2024年02月22日
    浏览(52)
  • 【Linux】冯诺依曼体系结构 && 操作系统 && 进程概念

    目录 一、冯诺依曼体系结构 二、操作系统  1、概念  2、设计OS的目的 三、进程  1、基本概念  2、描述进程-PCB  3、组织进程  4、查看进程和终止  5、通过系统调用获取进程标识符  6、通过系统调用创建进程-fork  7、进程状态  8、特殊进程    8.1 僵尸进程    8.2 孤儿进

    2024年02月10日
    浏览(58)
  • 【Linux】进程概念I --操作系统概念与冯诺依曼体系结构

    Halo,这里是Ppeua。平时主要更新C语言,C++,数据结构算法…感兴趣就关注我吧!你定不会失望。 计算机是由两部分组成的: 硬件+软件 .与硬件相关的为 冯诺依曼体系结构 ,与软件相关的为: 操作系统 . 如今大多数计算机(笔记本,服务器等)大多数都遵守冯诺依曼体系结构.实际中

    2024年02月09日
    浏览(35)
  • 操作系统理论:Linux进程与进程状态(进程调度的大O(1)算法数据结构模型)

    冯诺依曼体系的计算机在运行时,内存中会预加载许多程序(数据+运算指令集),然而CPU 同一时刻只能执行一个程序 (多个程序竞争CPU资源),此时就需要操作系统 对内存中的诸多程序进行管理 ,让CPU资源得到合理的分配,于是便有了进程的概念: 进程:描述程序的结构体对象( PCB结构体

    2024年02月15日
    浏览(46)
  • 【Linux操作系统】Linux中的进程和线程的概念、区别和实现的细节

    在Linux中,进程和线程是操作系统中两个重要的执行单位。它们是对程序运行时的抽象概念,用于管理和调度计算机资源。 进程是正在运行的程序的实例。它是操作系统分配资源和调度执行的基本单位。每个进程都有自己独立的内存空间,包含代码、数据、堆栈等。进程还包

    2024年02月14日
    浏览(53)
  • [入门篇]Linux操作系统fork子进程的创建以及进程的状态 超超超详解!!!我不允许有人错过!!!

    目录 0.前言 1.fork()创建子进程讲解 1.1fork()的简单介绍 1.2 创建子进程详解 1.2.1 如何理解fork创建子进程 1.2.2 子进程的PCB以及子进程的代码和数据 1.2.3为什么要共享写时拷贝 1.2.4 什么时候发生写时拷贝 1.3 fork函数返回值详解 1.3.1引入fork返回值的作用 1.3.2 fork返回执行逻辑剖析

    2024年03月21日
    浏览(62)
  • 操作系统(一):进程状态与进程调度

            操作系统作为计算机基础的四大件,系统学习无疑是十分重要的。在这个系列的文章中,荔枝会结合操作系统的知识进行归纳梳理,总结输出博文!下面这篇文章主要介绍的是进程状态和调度,重点是几种调度算法的理解和掌握,希望对正在学习的小伙伴有帮助

    2024年02月05日
    浏览(50)
  • 操作系统层面下——进程状态讲解

           目录         一.进程的状态:运行态         1.什么是运行状态?         2.进程进入内存的详细图解:         总结:         二.进程的状态:阻塞态          1.什么是阻塞状态?         三.进程的状态:挂起态         1.什么是挂起

    2024年02月06日
    浏览(32)
  • 操作系统进程线程(三)—进程状态、同步互斥、锁、死锁

    原子操作的概念 原子操作就是不可中断的一个或者一系列操作。 原子操作如何实现 总线锁定 使用处理器提供的一个LOCK#信号,当一个处理器在总线上输出此信号的时候,其他处理器的请求将被阻塞住,那么该处理器可以独占内存。 缓存锁 总线锁开销比较大,因为把CPU和内

    2024年02月04日
    浏览(51)
  • 【操作系统核心概念】进程管理和进程调度

    本文主要讲的是操作系统的一些核心概念, 主要讲解 进程管理和进程调度 的问题, 当然学习完本篇并不会让你能从零打造一个操作系统, 而只是让读者有了对操作系统核心概念的基本认识. 关注收藏, 开始学习吧🧐 操作系统是一组做计算机资源管理的软件的统称 , 其本质上也

    2024年02月12日
    浏览(61)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包