Heim > System-Tutorial > LINUX > Erfahren Sie mehr über Prozesse: Untergeordnete Prozesse, Thread-Informationen und allgemeine Status anzeigen

Erfahren Sie mehr über Prozesse: Untergeordnete Prozesse, Thread-Informationen und allgemeine Status anzeigen

PHPz
Freigeben: 2024-07-25 08:00:14
Original
388 Leute haben es durchsucht

Erfahren Sie mehr über Prozesse: Untergeordnete Prozesse, Thread-Informationen und allgemeine Status anzeigen

Q&A

ps查看所有子进程?pstree-ppid

ps-eLf各数组涵义?

PID:process id 进程id
PPID: parent process id 父进程id
LWP:表示这是个线程;要么是主线程(进程),要么是线程
NLWP: num of light weight process 轻量级进程数量,即线程数量
TIME: 占用的CPU总时间
C CPU利用率,以整数表示。
Nach dem Login kopieren

查看进程下的所有线程cpu借助率/显存/优先级等信息?top-H-p25120

查看线程在那个CPU上运行?ps-eoruser,pid,ppid,lwp,psr,args-L|grepl3-agent

常见的进程状态?

-D:不可被唤醒的睡眠状态,通常用于 I/O 情况。
-R:该进程正在运行。
-S:该进程处于睡眠状态,可被唤醒。
-T:停止状态,可能是在后台暂停或进程处于除错状态。
-W:内存交互状态(从 2.6 内核开始无效)。
-X:死掉的进程(应该不会出现)。
-Z:僵尸进程。进程已经中止,但是部分程序还在内存当中。
-<:高优先级(以下状态在 BSD 格式中出现)。
-N:低优先级。
-L:被锁入内存。
-s:包含子进程。
-l:多线程(小写 L)。
-+:位于后台。
Nach dem Login kopieren

进程的六种状态及其转换过程(生命周期)——就绪态,运行态,深度睡眠态,浅睡眠态,停止态,僵尸态。

母子进程共享的是?不同的是?——fork后,母子进程共享有(文件描述符、mmap构建的映射区。其他都是复制了一份,只是该进程的进程空间甚至进程地址完全跟父进程看着一样,而且完全是独立的空间了)

fork与vfork的区别——vfork用于创建一个新进程,而该新进程的目的是exec一个新程序。区别一:不将父进程的地址空间复制到子进程。区别二:vfork保证子进程先运行,在它调用exec或(exit)然后父进程才可能被调度运行。

**共享显存的地址值是在用户进程空间范围之内么?**fork以后子进程使用该地址和父进程是一样的么?若果是不同的进程,共享显存的进程空间中显示的地址是一样的么?

进程的生命周期,就绪态和运行态在数值上是相等的,都是由宏TASK_RUNNING定义。

Linux中Task_struct是怎样被管理的呢?

理解僵尸进程——放弃了几乎所有显存空间,没有任何可执行代码,也不能被调度,仅仅在进程列表中保留一个位置(资源早已释放,Task_struct结构还在)。假如他的父进程没安装SIGCHLD讯号处理函数调用wait()/waitpid()等待子进程结束,又没有显式忽视该讯号,这么它就仍然保持僵尸状态,假如父进程结束了,这么init进程手动会接手这个子进程,为它收尸LINUX社区,它还是能被消除的。假如父进程不会结束,子进程都会仍然保持僵尸状态,这就是为何系统中有时会有好多的僵尸进程。系统所能使用的进程号是有限的(cat/proc/sys/kernel/pid_max),假如大量的形成僵死进程,将由于没有可用的进程号而造成系统不能形成新的进程。

子进程回收:

父进程通过wait/waitpid等函数等待子进程结束,这会造成父进程挂起。假如父进程很忙,这么可以用signal函数为SIGCHLD安装handler,由于子进程结束后,父进程会收到该讯号,可以在handler中调用wait回收。假如父进程不关心子进程哪些时侯结束,这么可以用signal(SIGCHLD,SIG_IGN)通知内核,自己对子进程的结束不感兴趣,这么子进程结束后,内核会回收,并不再给父进程发送讯号还有一些方法,就是fork两次,父进程fork一个子进程,之后继续工作,子进程fork一个孙进程后退出,这么孙进程被init接管,孙进程结束后,init会回收。不过子进程的回收还要自己做。

子进程结束后为何要步入僵尸状态?——因为父进程可能要取得子进程的退出状态等信息。

Ist der Zombie-Zustand ein Zustand, den jeder untergeordnete Prozess durchlaufen muss? - Jeder untergeordnete Prozess (außer init) verschwindet nicht sofort nach exit(), sondern hinterlässt eine Datenstruktur namens Zombie-Prozess (Zombie) (er belegt etwas Videospeicher). Ressourcen, d. h. es gibt noch einen Datensatz in der Prozesstabelle) und warten auf die Verarbeitung durch den übergeordneten Prozess. Wenn der übergeordnete Prozess nach exit() keine Zeit hat, den untergeordneten Prozess zu verarbeiten, können Sie mit dem Befehl ps feststellen, dass der Status des untergeordneten Prozesses „Z“ ist. Wenn der übergeordnete Prozess beendet wird, bevor der untergeordnete Prozess endet, wird der untergeordnete Prozess von init übernommen. init verarbeitet den untergeordneten Prozess im Zombie-Zustand als übergeordneten Prozess.

So eliminieren Sie Zombie-Prozesse:

Schreiben Sie den übergeordneten Prozess neu und sammeln Sie den Hauptteil des untergeordneten Prozesses nach seinem Tod. Die spezifische Methode besteht darin, das SIGCHLD-Signal zu akzeptieren. Nachdem der untergeordnete Prozess gestorben ist, wird das SIGCHLD-Signal an den übergeordneten Prozess gesendet. Nachdem der übergeordnete Prozess dieses Signal empfangen hat, führt er die Funktion waitpid() aus, um die Leiche des untergeordneten Prozesses einzusammeln. Dies basiert auf dem Prinzip, dass der Kernel ihm eine SIGCHLD-Nachricht sendet, auch wenn der übergeordnete Prozess nicht aufruft. Obwohl die Standardverarbeitung darin besteht, sie zu ignorieren, können Sie eine Verarbeitungsfunktion festlegen, wenn Sie auf diese Nachricht antworten möchten . SIGCHLD-Signal: Wenn der untergeordnete Prozess endet, empfängt der übergeordnete Prozess dieses Signal. Wenn der übergeordnete Prozess dieses Signal nicht verarbeitet und nicht auf den untergeordneten Prozess wartet, wird der untergeordnete Prozess tatsächlich beendet und belegt einen Eintrag in der Kernel-Prozesstabelle. Zu diesem Zeitpunkt wird der untergeordnete Prozess als Zombie-Prozess bezeichnet. Wir sollten diese Art von Situation vermeiden (der übergeordnete Prozess ignoriert entweder das SIGCHILD-Signal oder fängt es ab oder wartet auf den untergeordneten Prozess, den er erzeugt, oder der übergeordnete Prozess wird zuerst beendet und dann wird die Beendigung des untergeordneten Prozesses manuell von übernommen). der Init-Prozess).

Die Funktion „exit()“, wenn der Prozess beendet wird. Was sind also die Thread-Abschlüsse? ——Drei Situationen für den Thread-Abbruch:

Der Thread kehrt einfach von der Startfunktion zurück und der Rückgabewert ist der Exit-Code des Threads. Threads können von anderen Threads im selben Prozess abgebrochen werden. Der Thread ruft pthread_exit auf.

Wenn Sie nicht auf einen Thread warten und sich nicht für den Rückgabewert des Threads interessieren, können Sie den Thread in den getrennten Zustand versetzen und das System die von ihm belegten Ressourcen beim Beenden des Threads manuell zurückfordern lassen. Ein Thread kann pthread_detach nicht selbst aufrufen, um in den getrennten Zustand zu wechseln. Er kann pthread_detach nur von anderen Threads aufrufen.

pthread_cancel() ermöglicht es einem Thread, einen anderen durch th angegebenen Thread abzubrechen.

Prozess – die kleinste Einheit der Ressourcenzuweisung, Thread – die kleinste Einheit der Programmausführung. Ein Prozess verfügt über einen unabhängigen Adressraum, und ein Thread hat keinen unabhängigen Adressraum (Threads im selben Prozess teilen sich den Adressraum des Prozesses. Nach einem Prozessabsturz hat dies keine Auswirkungen auf andere Prozesse im geschützten Modus Thread ist nur ein Teil eines Prozesses. Verschiedene Ausführungspfade. Threads haben ihre eigenen Stapel und lokalen Variablen, aber Threads haben keine separaten Adressräume. Wenn ein Thread hängen bleibt, bedeutet dies, dass der gesamte Prozess abgelaufen ist. Daher sind Multiprozessprogramme stärker als Multithreadprogramme verbrauchen mehr Ressourcen beim Wechseln von Prozessen. Für einige gleichzeitige Vorgänge, die den gleichzeitigen Betrieb und die gemeinsame Nutzung einzelner Variablen erfordern, können jedoch nur Threads und keine Prozesse verwendet werden.

Grund für die Verwendung von Multithreading?

Prozess

Prozess ist die Grundeinheit der Ressourcenzuweisung und Thread ist die Grundeinheit der Planung

Prozessinformationen

Der Linux-Scheduler identifiziert tatsächlich task_struct für die Planung. Unabhängig vom Prozessthread entspricht die unterste Ebene einer task_struct. Der Unterschied zwischen einem Prozess und einem Thread besteht in der Anzahl der gemeinsam genutzten Ressourcen. Die beiden Prozesse teilen sich keine Ressourcen, und alle Ressourcen werden von den beiden Threads gemeinsam genutzt.

PCB(ProcessControlBlock) Prozesssteuerungsblock

task_struct ist die Beschreibung eines Prozesses durch den Linux-Kernel, der auch als „Prozessdeskriptor“ bezeichnet werden kann. Eine Beschreibung der Struktur, in der alle für den Prozess erforderlichen Ressourcen gespeichert sind. /proc/${pid} prozessbezogene Informationen. Für das Betriebssystem ist ein Prozess eine Datenstruktur.

struct task_struct {
longstate; // 进程状态-1为不可运行, 0为可运行, >0为已中断

struct mm_struct*mm; // 指向的是进程的虚拟内存,也就是载入资源和可执行文件的地方
	pid_t pid; // 进程标识符,用来代表一个进程
 
struct task_struct __rcu*parent; // 指向父进程的指针
struct list_headchildren; // 子进程列表
 	struct list_head sibling; // 兄弟进程
struct fs_struct*fs;// 存放文件系统信息的指针
 
struct files_struct *files; // 一个数组,包含该进程打开的文件指针
unsigned int policy; // 调度策略:一般有FIFO,RR,CFS
...
};
Nach dem Login kopieren

从2.6版本之后,Linux改用了slab分配器动态生成task_struct,只须要在栈底(向上下降的栈)或栈顶(向下下降的栈)创建一个新的结构structthread_info(这儿是栈对象的尾端),你可以把slab分配器觉得是一种分配和释放数据结构的优化策略。通过预先分配和重复使用task_struct,可以防止动态分配和释放带来的资源消耗。

进程的地址空间ref

所谓进程地址空间(processaddressspace),就是从进程的视角听到的地址空间,是进程运行时所用到的虚拟地址的集合。

进程的显存

程序段(Text):程序代码在显存中的映射,储存函数体的二补码代码。

初始化过的数据(Data):在程序运行初早已对变量进行初始化的数据。

未初始化过的数据(BSS):在程序运行初未对变量进行初始化的数据。

栈(Stack):储存局部、临时变量,函数调用时,储存函数的返回表针,用于控制函数的调用和返回。在程序块开始时手动分配显存,结束时手动释放显存,其操作方法类似于数据结构中的栈。

堆(Heap):储存动态显存分配,须要程序员手工分配,手工释放.注意它与数据结构中的堆是两码事,分配方法类似于数组。

注:1.Text,BSS,Data段在编译时早已决定了进程将占用多少VM

可以通过size,晓得这种信息:

正常情况下,Linux进程不能对拿来储存程序代码的显存区域执行写操作,即程序代码是以只读的形式加载到显存中,但它可以被多个进程安全的共享。

创建进程后都创建了什么资源

进程创建

system()通过调用shell启动一个新进程

exec()以替换当前进程映像的方法启动一个新进程

fork()以复制当前进程映像的方法启动一个新进程

fork(2)

执行fork后,父进程的task_struck对拷给子进程,母子进程最初资源完全一样,而且是两份不同的拷贝,因而任何改动都导致两者的分裂。

兄妹进程对显存资源(mm)的管理使用了COW(Copy-On-Write,写时拷贝)技术:

在fork之前,一片显存区对应一份数学地址和一份虚拟地址,显存区的权限为RW;在fork以后,母子进程听到的显存区虚拟地址相同,化学地址也相同,母女进程使用的虽然是同一片化学显存,未发生显存拷贝,操作系统会将此显存区权限改为RO;父或子进程对显存区执行写操作将触发PageFault,操作系统此时会将显存区拷贝一份,母女进程见到的虚拟地址仍旧一样,而且化学地址早已不同。各进程虚拟地址到化学地址的映射由MMU(MemoryManagementUnit,显存管理单元)管理。fork运行在有MMU的CPU上。

For CPUs without MMU, it is difficult to apply COW and support fork. CPUs without MMU use vfork to create processes, and the parent process will always block until the child process exits or execs. The essential difference between vfork and fork is that the mother and child processes in vfork share the same video memory area.

The

fork(2) system call is used to create a new process, called a child process, which runs at the same time as the parent process (concurrent), and the running order is uncertain (asynchronous). pid_t is a macro definition, its essence is int. If successful, it returns two values, the child process returns 0, and the parent process returns the child process ID; otherwise, an error returns -1

The entire virtual address space of the parent is copied in the child process, including the status of the mutex lock,

The child process is exactly the same as the parent process, except for the following points:

Process recycling wait() and waitpid()

Recycle the task_struct structure of the child process through waitpid()/wait().

Difference:

Orphan Processes and Zombie Processes Zombie Processes

Zombie process: A process uses fork to create a child process. If the child process exits and the parent process does not call wait or waitpid to obtain the status information of the child process, the process descriptor of the child process is always saved in the system. These processes are called zombie processes. (The child process can be seen through /proc/$pid, but the thread is not)

When a process calls the exit command to end its life, although it is not really destroyed, it leaves behind a data structure called a zombie process (Zombie) (the system calls exit, its function is to make the process Exit, but it is only limited to turning a normal process into a zombie process, and cannot completely destroy it).

In the status of Linux processes, the zombie process is a very special kind. It has already given up almost all the video memory space. It does not have any executable code and cannot be scheduled. It only retains a position in the process list to record the process. Exit status and other information can be collected by other processes. In addition, the zombie process no longer occupies any video memory space. It needs its parent process to collect the corpse for it.

If its parent process does not install the SIGCHLD signal processing function and calls wait or waitpid() to wait for the child process to end, and does not explicitly ignore the signal, then it will still remain in the zombie state. If the parent process ends at this time, then the init process Manually will take over this sub-process and collect its corpse, and it can still be eliminated.

And if the parent process is a loop and will not end, then the child process will still remain in the zombie state. This is why there are sometimes many zombie processes in the system. The process numbers that can be used by the system are limited. If a large number of zombie processes are formed, the system will not be able to form new processes because there are no available process numbers.

Cause of zombie process: After the child process ends, it sends the SIGCHLD signal to the parent process, and the parent process ignores it by default; the parent process does not call the wait() or waitpid() function to wait for the end of the child process. Ways to prevent zombie processes: The parent process calls wait()/waitpid() to wait for the child process to end. In this way, the parent process will usually be blocked at wait and cannot handle other things. Capture the SIGCHLD signal and call the wait function on the signal processing function. This processing can prevent the problem described in 1. Fork twice, the parent process creates a father process, and the father process creates a son process. After that, the mother process commits suicide, and the son process becomes an orphan process and is taken in by the init process. Orphan process

Orphan process: The parent process exits, but one or more of its child processes are still running, so these child processes will become orphan processes. Orphan processes will be taken in by the init process (pid=1), and the init process will complete status collection for them. (If an orphan process appears in the system, it means that the main process did not clear the child processes before exiting)

Thread (LightweightProcess, LWP)

同一进程的多个线程获取进程ID时得到的是惟一ID值。Linux同一进程的多线程,在内核视角实际上每位线程都有一个PID,但在用户空间须要getpid()返回惟一值,Linux使用了一个小方法,引入了TGID的概念linux进程与线程 内核,getpid()返回的的TGID值。

pthread_create()

Linux线程本质上就是进程,只是与进程间资源共享方法不同,线程间共享所有资源。每位线程都有自己的task_struct,因而每位线程都可被CPU调度。多线程间又共享同一进程资源。

在一个线程中创建了另外一个线程,主线程要等到创建的线程返回了,获取该线程的返回值后主线程才退出。这个时侯就须要用到线程挂起。pthread_join函数用于挂起当前线程,直到指定的线程中止为止。

说线程的PID,是指用户空间的进程ID,值就是TGID(threadgroupIDforthethreadgroupleader);当非常强调,线程在内核空间的PID,则指线程在内核中task_struct里特有的PID。top–H命令从线程视角显示CPU占用率。不带参数的top命令,进程ID是主线程的PID(也就是TGID)。

Linux的进程和线程

进程是处于运行期的程序和相关资源的统称,具备一些要素:

拥有一段可执行程序代码。如同一场戏须要一个剧本。代码段可以多个进程共用,如同许多场表演都可以用一份剧本一样。拥有一段进程专用的系统堆栈空间。可以觉得是这个进程的“私有财产”,相应的,也肯定有系统空间堆栈在系统中有进程控制块(或称进程描述符,本文两种说法通用)描述这个进程的相关信息。可以觉得是进程的“户口”。系统通过这个控制块来控制进程的相关行为有独立的储存空间,也就是专有的用户空间,相应的又会有用户空间堆栈。理解各类ID

# ps -eo ppid,pid,tid,lwp,tgid,pgrp,sid,tpgid,args -L | awk &#039;{if(NR==1) print $0; if($9~/a.out/) print $0}&#039;
 PPID PID TID LWPTGIDPGRP SID TPGID COMMAND
 579046 2436128 2436128 2436128 2436128 2436128579046 2436128 ./a.out
 579046 2436128 2436129 2436129 2436128 2436128579046 2436128 ./a.out
 579046 2436128 2436130 2436130 2436128 2436128579046 2436128 ./a.out
Nach dem Login kopieren

pidstat-t[-ppid号]可以复印出线程之间的关系。

各类ID最后都归结到pid和lwp(tid)上。所以理解各类ID,最终归结为理解pid和lwp(tid)的联系和区别。

PID:进程ID。

LWP:线程ID。在用户态的命令(例如ps)中常用的显示方法。

TID:线程ID,等于LWP。TID在系统提供的插口函数中更常用,例如syscall(SYS_gettid)和syscall(__NR_gettid)。

TGID:线程组ID,也就是线程组leader的进程ID,等于PID。

pgid(processgroupID):进程组ID,也就是进程组leader的进程ID。

pthreadid:pthread库提供的ID,生效范围不在系统级别,可以忽视。

sid:sessionIDforthesessionleader。

TPGID:ttyprocessgroupIDfortheprocessgroupleader。

上图挺好地描述了用户视角(userview)和内核视角(kernelview)看见线程的差异:

轮询

Polling (user-level thread), which is transparent to the kernel, that is, the system does not know the existence of polling. It is completely scheduled by the user's program itself. Because it is controlled by the user program itself, it is difficult to Like occupying scheduling, which forces the CPU control to switch to other processes/threads, generally only cooperative scheduling can be performed. After the polling itself actively sells the control, other polling can be executed.

The difference between goroutine and interpreter

Essentially, goroutine is polling. The difference is that Golang encapsulates and processes goroutine scheduling in many aspects such as runtime and system calls. When it encounters long-term execution or system calls, it will actively sell the CPU (P) of the current goroutine to other goroutines. Can be scheduled and executed Linux operation and maintenance recruitment, that is, Golang supports the interpreter from the language level.

Different process scheduling in other aspects

Three main scheduling strategies of the Linux kernel:

1, SCHED_OTHER time-sharing scheduling strategy,

2, SCHED_FIFO real-time scheduling strategylinux process and thread kernel, first come first served

3, SCHED_RR real-time scheduling strategy, time slice rotation

Real-time process scheduling

SCHED_FIFO: Different priorities are moved to sleep according to the higher priority, and then run according to the lower priority; the same priority is first in, first out.

SCHED_RR: Different priorities will be moved to sleep according to the higher priority, and then run according to the lower priority; equal priority rotation.

Kernel RT patch:

The following two parameters

/proc/sys/kernel/sched_rt_period_us

/proc/sys/kernel/sched_rt_runtime_us

Indicates that RT can only run up to the runtime time during the period

Normal process scheduling

SCHED_OTHER:

CFS: Completely Fair Scheduling (new kernel)

Black mangrove, the value of the right node is greater than the value of the left node

Run vruntime’s smallest process so far

Considering both CPU/IO and nice

Always find the thread schedule with the smallest vruntime.

vruntime=pruntime/weight×1024;

vruntime is the virtual running time, pruntime is the chemical running time, and the weight is determined by the nice value (the lower the niceness, the higher the weight). Threads with less running time and lower nice values ​​will have smaller vruntime and will be prioritized for scheduling. This is a process that changes dynamically with operation.

Kernel space and user space Kernel space and user space

The virtual address space of Linux ranges from 0 to 4G. The Linux kernel divides this 4G byte space into two parts, and the highest 1G byte (from virtual address 0xCxC0000000 to 0xFFFFFFFF) is used by the kernel, which is called "kernel space" ". The lower 3G bytes (from virtual address 0x00000000 to 0xBFFFFFFF) are used by each process, called "user space. Since each process can step into the kernel through system calls, the Linux kernel is shared by all processes in the system. . So, from a specific process perspective, each process can have 4G bytes of virtual space

.

Linux uses a two-level protection mechanism: Level 0 is used by the kernel, and Level 3 is used by user programs. Each process has its own private user space (0~3G). This space is invisible to other processes in the system. The highest The 1GB of virtual kernel space is shared by all processes and the kernel.

The kernel space stores kernel code and data, while the user space of the process stores the code and data of the user program. Whether it is kernel space or user space, they are all in virtual space. In fact, the kernel space occupies the highest 1GB byte of each virtual space, but it is always mapped to the chemical memory from the lowest address (0x00000000). In addition, the use of virtual addresses can effectively protect the kernel space from being destroyed by user space. The virtual address The chemical address conversion process is completed by the operating system and the CPU together (the operating system sets the page table for the CPU, and the CPU performs address conversion through the MMU unit).

Note: Each process in the multi-tasking operating system runs in its own video memory sandbox. This sandbox is the virtual address space (virtual address space). In 32-bit mode, it is always a 4GB video memory address. piece. This virtual address is mapped to chemical memory through a page table (pagetable), which is maintained by the operating system and referenced by the processor. Each process has its own set of page tables.

The process memory space distribution is shown on the right:

Video memory

The heap goes down and the stack goes up (why is mine the other way around???)

The descending direction and big and small endianness of stack and memory

Low->|----------------|

|Global quantities (all initialized quantities.data, |

|Uninitialized quantity.bss)|

Start of heap->|----------------|

|The heap drops towards the high address|

||

||

|Free space|

||

||

|The stack moves down to the lower address|

Start of high stack->|----------------|

Das obige ist der detaillierte Inhalt vonErfahren Sie mehr über Prozesse: Untergeordnete Prozesse, Thread-Informationen und allgemeine Status anzeigen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:itcool.net
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage