Inter-process relationships

Source: Internet
Author: User
Tags posix unique id

POSIX requires multiple thread inside a process to share a PID,

However, in Linux kernel, either process or thread, a task struct is assigned and a unique PID is assigned (the PID is actually the thread ID).

In this way, to satisfy POSIX threading rules, Linux introduces the concept of thread groups, the PID that is shared by all threads in a process is called the thread group ID, which is the Tgid member in the task struct.

Therefore, in Linux kernel, the thread group ID (tgid,thread group ID) is the traditional process ID.

For getpid system calls, the Linux kernel returns TGID. For Gettid system calls, the intent is to return the thread ID, and in the Linux kernel, the PID member of the task struct is returned.

Word, the POSIX process ID is the thread group ID in Linux. The POSIX thread ID is the PID in Linux.

We can get the status information of the process by the following command:

# cat/proc/1350/stat   1350 (system_server) S 451 451 0 0-1 4194624 169945 0 1536 ...

Where the first number is the three numbers after pid,s are ppid, Pgid, and SIDS, respectively.

# cat/proc/1350/status                                       Name:    system_serverstate:    S (sleeping)tgid:    1350Pid:    1350PPid:    451 Tracerpid:    0 ...

With the above two commands, you can list the relationships between the following more typical processes:

Comm PID Ppid Tgid Pgid Sid
Init 1 0 1 0 0
Kthreadd 2 0 2 0 0
ksoftirqd/0 3 2 3 0 0
Zygote64 451 1 451 451 0
Zygote 452 1 452 452 0
System_server 1350 451 1350 451 0
Packagemanager 1454 451 1350 451 0
Com.miui.video 7041 452 7041 451 0

Process number No. 0: The swapper process, aka Idle process, the first execution flow at kernel startup. Responsible for initializing the kernel modules, creating the init process and the ktheadd process, and finally entering the idle loop, which is responsible for the idle management and CPU hot-swapping transactions.

Process 1th: The init process, the first process of user space, and the ancestor process of all user-state processes, is responsible for creating and managing individual native processes.

Process Number 2nd: Kthreadd process, kernel thread ancestor process, responsible for creating ksoftirqd/0 and other kernel threads.

ksoftirqd/0: Kernel thread, can only execute in kernel state.

Zygote process: Init created, there are 64-bit and 32-bit two, all Java processes are hatched by them, they are the parent process of all Java processes.

System_server process: Android core process, line Line 1350 is its main thread

Packagemanager thread: A child thread in the System_server process.

Com.miui.video: A common 32-bit Java process.

"pid"

Represents the ID of a dispatch unit task:

struct Task_struct {    ...    pid;    ...}

The dispatch unit is the execution flow, and each execution flow corresponds to a task_struct. Each task_struct has a unique ID that is the PID.

"Ppid"

One task_struct can create another task_struct, both with a parent-child relationship, and Ppid is the parent execution flow of an execution flow.

But this parent-child relationship is not absolute, such as:

Static struct Long clone_flags,...) {    ...     /*  *    /if (Clone_flags & (clone_parent|  clone_thread)) {        p->real_parent = current->real_parent;     Else {        p->real_parent = current ;    }    ...}

If you set Clone_thread or clone_parent when you create a task_struct,

The parent execution flow of the creator is the parent execution flow of the current execution stream, otherwise the parent execution flow of the creator is the current execution stream.

For example, Packagemanager (1454) was created by the main thread of System_server (1350),

But the ppid of 1454 is not 1350, but 451, that is, the parent of the 1350 zygote64 the main thread of the execution stream.

"Tgid"

One or more threads can form a group of threads, and each thread in the thread group shares the resources of address space, signal processing functions, File table comfort, and so on.

The PID of the main thread in the threading group is the tgid of the thread to which this thread group belongs.

For example, Packagemanager (1454) and System_server (1350) belong to one thread group, Tgid is 1350.

Threads are created by using the Pthread_create () function:

intPthread_create (pthread_t* thread_out, pthread_attr_tConst* attr,void* (*start_routine) (void*),void*Arg)  {  .. intFlags = CLONE_VM | Clone_fs | Clone_files | Clone_sighand | clone_thread | Clone_sysvsem |Clone_settls| Clone_parent_settid |Clone_child_cleartid; intrc =Clone(__pthread_start, Child_stack, Flags, Thread, & (Thread->tid), TLS, & (thread->tid)); ...} AsmlinkageintSys_clone (unsignedLongClone_flags, unsignedLongnewsp,int__user *parent_tidptr,intTls_val,int__user *child_tidptr,structPt_regs *regs) {    if(!newsp) newsp= regs->arm_sp; return do_fork(Clone_flags, NEWSP, Regs,0, Parent_tidptr, child_tidptr);}LongDo_fork (unsignedLongclone_flags, unsignedLongStack_start,structPt_regs *regs, unsignedLongStack_size,int__user *Parent_tidptr,int__user *child_tidptr) {... p= copy_process(clone_flags, Stack_start, Regs, Stack_size, Child_tidptr, NULL, Trace); ...}Static structTask_struct *copy_process (unsignedLongclone_flags, unsignedLongStack_start,structPt_regs *regs, unsignedLongStack_size,int__user *Child_tidptr,structPID *PID,intTrace) {... p->tgid = p->pid;//Tgid default to its own PID    if(Clone_flags & clone_thread) p->tgid = current->tgid;//Tgid is the tgid of the current thread    ...}

"Pgid"
The thread group mentioned above is actually the process we often talk about.

Multiple processes can also form groups called process groups, and the main thread of its lead process is PID pgid.

First, the process group ID is inherited from the parent process by default, but Init modifies the pgid after the Naitive service is created.

voidService_start (structService *svc,Const Char*Dynamic_args) {... pid_t pid=Fork (); if(PID = =0) {//Child Process        ... Setpgid (0, Getpid ()); ...    }} Syscall_define2 (Setpgid, pid_t, PID, pid_t, Pgid) {structTask_struct *p; structTask_struct *group_leader = current->group_leader;//the grop_leader of native process is self    structPID *pgrp; if(!pid)//If the incoming PID is 0, thePID =TASK_PID_VNR (Group_leader); PID=TASK_PID_VNR (Group_leader); P=find_task_by_vpid (PID); Pgrp=task_pid (P); if(Pgid! =pid) {... pgrp=find_vpid (Pgid); }    if(TASK_PGRP (p)! = PGRP)//The original pgrp is process No. 0, and the new PGRP is the current process itself        Change_pid(P,Pidtype_pgid, PGRP);//Modify Pgid to the current process itself    ...}

Setpgid (0, Getpid ()) is actually to set their own pgid PID,

So all init-created native processes, their pgid is their own PID.

If there is no special setting, the child process inherits the gpid of the parent process. What's the use of doing this?

The original Init after receiving the child process exit signal SIGCHLD, will directly the child process belongs to the process group of all processes killed, the code is as follows:

Static BOOLwait_for_one_process () {intstatus; pid_t PID= Temp_failure_retry (Waitpid(-1, &status, Wnohang)); ... service* Svc =service_find_by_pid (PID); ...    if(! (Svc->flags & svc_oneshot) | | (Svc->flags &Svc_restart)) {NOTICE ("Service '%s ' (PID%d) killing any children in process group\n", svc->name, PID); Kill (-pid,SIGKILL);//This will kill all the processes in the process group.    }}

In general, when we call with the kill system, the incoming PID is a positive number, but here the negative number is passed in.

Kill system calls the positive PID will kill the thread group, negative PID will kill the process group.

The relevant code is as follows:

Syscall_define2 (Kill, pid_t, PID,int, SIG) {    structSiginfo Info; Info.si_signo=Sig; Info.si_errno=0; Info.si_code=Si_user; Info.si_pid=TASK_TGID_VNR (current); Info.si_uid=Current_uid (); return Kill_something_info(Sig, &info, pid);}Static intKill_something_info (intSigstructSiginfo *info, pid_t pid) {    intret; if(PID >0) {ret=Kill_pid_info(SIG, Info, Find_vpid (PID));//Kill Thread Group        returnret; }    if(PID! =-1) {ret=__kill_pgrp_info(SIG, Info, PID find_vpid (-pid): Task_pgrp (current));//Kill Process Group}Else {        ...     } returnret;}

So zygote created all the sub-processes, its pgid are zygote pid, so zygote hangs, its child process will be killed by Init.

There are two zygote,zygote64 and zygote32 under 64 digits.

The parent process of the 64-bit application is zygote64, and its pgid is also the PID of Zygote64;

The parent process of the 32-bit app is Zygote32, and its pgid is zygote64 PID, what's going on?

It turns out that regardless of the 32-bit or 64-bit zygote, it calls Setchildpgid () to change the pgid of the child process after the child process is created.

The following code:

    Private void setchildpgid (int  pid) {        try  {            Os.  Setpgid(PID, Os.  Getpgid(peer.  Getpid()));         Catch (Errnoexception ex) {            ...        }    }

The peer here is the end of the socket, which is system_server. And System_server's Pgid is Zygote64 's PID.

In this way, all zygote32 created by the child process, their pgid are zygote64 pid.

For example:

Comm PID Ppid Tgid Pgid Sid
Com.miui.video 7041 452 7041 451 0

The parent process of Com.miui.video () is zygote32 (452), but its pgid is zygote64 (451).

So as the following RC:

Service Zygote_secondary/system/bin/app_process32-xzygote/system/bin--zygote--socket-name=zygote_secondary    Class main    socket zygote_secondary stream 660 root system    Onrestart restart Zygote

When Zygote32 exits the restart, it also restarts zygote64, so that the process created zygote32 can exit.

But strange inter-process relationships can be problematic in some cases, such as: http://www.cnblogs.com/YYPapa/p/6848806.html

"Sid"

Most of the cases in Android do not use a SID, most of the SID is 0, only with the SH program will set this SID, here is not expanded.

Inter-process relationships

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.