Windows operation process
Function analysis
Create process
Under Windows, a process can be created by calling createp process() system. The parameters passed in and their meanings are as follows
BOOL CreateProcess( LPCTSTR lpApplicationName, // Application name LPTSTR lpCommandLine, // Command line string LPSECURITY_ATTRIBUTES lpProcessAttributes, // Security properties of the process LPSECURITY_ATTRIBUTES lpThreadAttributes, // Thread security properties BOOL bInheritHandles, // Inherit the properties of the parent process DWORD dwCreationFlags, // Create flag LPVOID lpEnvironment, // Points to a newly created environment block LPCTSTR lpCurrentDirectory, // Pointer to the current directory name LPSTARTUPINFO lpStartupInfo, // Information passed to the new process LPPROCESS_INFORMATION lpProcessInformation // Information returned by the new process );
About the structure of lpProcessInformation
typedef struct _PROCESS_INFORMATION { HANDLE hProcess;//The handle of the process can be used to end the process. The handle must have PROCESS_TERMINATE access. HANDLE hThread; DWORD dwProcessId; DWORD dwThreadId; } PROCESS_INFORMATION, *LPPROCESS_INFORMATION;
Destruction process
The destruction process can adopt the following two methods
void ExitProcess( UINT uExitCode );
BOOL WINAPI TerminateProcess( __in HANDLE hProcess,//Handle to the process to terminate __in UINT uExitCode//The exit code that will be used by processes and threads that terminate as a result of this call. ); //Handle must have PROCESS_TERMINATE access.
There is a process with the same name. Using TerminateProcess() to destroy it will fail
Linux operating system
summary
Create process commands for linux
- fork() copies all the resources of the parent process to the child process;
- vfork() divides the parent process by mm_ Copy all the resources of struct to the child process;
- clone() is through CLONE_XXX specifies which resources to copy from the parent process to the child process
Fork, VFORK and clone are essentially to the kernel_ The call of clone function is different in the parameters passed in
A successful fork() call returns 0. In the parent process, fork() returns the pid of the child process. If an error occurs, fork returns a negative value. The following similarities exist between parent and child processes
-
The pid of the child process is newly allocated, which is different from the parent process.
-
The ppid of the child process will be set as the pid of the parent process.
-
The resource statistics in the child process will be cleared.
-
Any pending signals are cleared and will not be inherited by the child process (see Chapter 9).
-
No file locks are inherited by child processes.
fork
Check the commit record cad6967ac10843a70842cd39c7b53412901dd21f and find it in V5 10-rc1 replace the original_ do_fork replaced with kernel_clone
#ifdef __ARCH_WANT_SYS_FORK SYSCALL_DEFINE0(fork)//Refer to kernel / sys for system call definition C 0 means that the fork system call requires 0 parameters { #ifdef CONFIG_MMU struct kernel_clone_args args = { .exit_signal = SIGCHLD, }; return kernel_clone(&args); #else /* can not support in nommu mode */ return -EINVAL; #endif } #endif
The fork function returns twice, one in the parent process and the other in the child process. If the return value is 0, it indicates that it is a child process; If the return value is a positive number, it indicates that it is the parent process
vfork
#ifdef __ARCH_WANT_SYS_VFORK SYSCALL_DEFINE0(vfork) { struct kernel_clone_args args = { .flags = CLONE_VFORK | CLONE_VM, .exit_signal = SIGCHLD, }; return kernel_clone(&args); } #endif
kernel_clone
pid_t kernel_clone(struct kernel_clone_args *args)//pid_t returns the process number for the process number type function { u64 clone_flags = args->flags; struct completion vfork; struct pid *pid; struct task_struct *p; //Create process descriptor structure pointer int trace = 0; pid_t nr; /* * For legacy clone() calls, CLONE_PIDFD uses the parent_tid argument * to return the pidfd. Hence, CLONE_PIDFD and CLONE_PARENT_SETTID are * mutually exclusive. With clone3() CLONE_PIDFD has grown a separate * field in struct clone_args and it still doesn't make sense to have * them both point at the same memory location. Performing this check * here has the advantage that we don't need to have a separate helper * to check for legacy clone(). */ if ((args->flags & CLONE_PIDFD) && (args->flags & CLONE_PARENT_SETTID) && (args->pidfd == args->parent_tid)) return -EINVAL; /* * Determine whether and which event to report to ptracer. When * called from kernel_thread or CLONE_UNTRACED is explicitly * requested, no event is reported; otherwise, report if the event * for the type of forking is enabled. */ if (!(clone_flags & CLONE_UNTRACED)) { if (clone_flags & CLONE_VFORK) trace = PTRACE_EVENT_VFORK; else if (args->exit_signal != SIGCHLD) trace = PTRACE_EVENT_CLONE; else trace = PTRACE_EVENT_FORK; if (likely(!ptrace_event_enabled(current, trace))) trace = 0; } // Copy the process descriptor and return the created task_ Pointer to struct p = copy_process(NULL, trace, NUMA_NO_NODE, args); /*add_latent_entropy()See Linux / random H is equivalent to add_device_randomness() is used to generate random numbers *Linux The kernel uses entropy to describe the randomness of data *Linux The kernel maintains an entropy pool to collect ambient noise from device drivers and other sources. *It can generate true random number sequence. */ add_latent_entropy(); //IS_ERR() is actually judging the pointer if (IS_ERR(p)) return PTR_ERR(p); //Then convert the pointer to long type data /* * Do this prior waking up the new thread - the thread pointer * might get invalid after that point, if the thread exits quickly. */ trace_sched_process_fork(current, p); // Get the pid in the newly created process descriptor pid = get_task_pid(p, PIDTYPE_PID);//Used to find the corresponding struct pid according to task and pid type nr = pid_vnr(pid);//The return value is pid_ A variable of type T, which represents the global process number of the obtained process. The parameter pid is a pointer variable of type struct pid if (clone_flags & CLONE_PARENT_SETTID) put_user(nr, args->parent_tid); //If vfork is used, initialize vfork to complete processing information and ensure that the parent process runs after if (clone_flags & CLONE_VFORK) { p->vfork_done = &vfork; init_completion(&vfork); get_task_struct(p); } // Add the subprocess to the queue of the scheduler, so that the subprocess has the opportunity to get the CPU wake_up_new_task(p); //fork is completed and the child process will start running if (unlikely(trace)) ptrace_event_pid(trace, pid); // If it is vfork, insert the parent process into the waiting queue and suspend the parent process until the child process releases its own memory space // Ensure that the child process runs first with the parent process if (clone_flags & CLONE_VFORK) { if (!wait_for_vfork_done(p, &vfork)) ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid); } put_pid(pid);//Used to free the Cache space occupied by the process return nr; }
copy_process
- Execute dup_task_struct(), copy the current process task_struct
- Check whether the number of processes exceeds the maximum allowed by the system (32678 by default)
- Execute sched_fork(), set the scheduler related information, and set the task process status to TASK_RUNNING and allocating CPU resources
- Execute copy_xxx(), copy the files, fs, mm, io, sighand, signal and other information of the process
- Execute copy_thread_tls(), copy the kernel stack information of the child process
- Execute alloc_pid(), assign a new pid to the new process
Reference link
https://www.cnblogs.com/sky-heaven/p/5715066.html
https://blog.csdn.net/notbaron/article/details/80033417
https://www.coolcou.com/linux-kernel/linux-process-management-kernel-api
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa
https://github.com/torvalds/linux