In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-21 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article shows you how the fork function in linux creates a new process, which is concise and easy to understand, and can definitely brighten your eyes. I hope you can get something through the detailed introduction of this article.
Now that we've talked about kernel loading and system boot, let's take a look at how the kernel's do_fork () function creates a new process.
In the Linux kernel, the response functions of the system call fork () function for the user to create a process are sys_fork (), sys_clone (), and sys_vfork (). All three functions are implemented by calling the kernel function do_fork (). According to
The work done by the do_fork () function varies according to the clone_flags parameters used in the call.
This part is simple and I am not going to analyze it. Let's focus on how the following do_fork () function works.
We know that the do_fork () function generates a new process, roughly divided into three steps.
1. Establish the process control structure and assign the initial value to make it a process image. This process completes the following.
Allocate an task_struct data structure in memory to represent the new process that will be generated.
Copy the contents of the parent process PCB to the PCB of the new process.
Assign a unique process identification number PID and user_struct structure to the new process. Then check that the user has the resources necessary to execute a new process.
Reset the data members in the task_struct structure that are different from the parent process values.
Set the process management information and decide whether to copy the selected parts of the parent process task_struct, such as the pointer fs, files pointer, etc., according to the provided clone_flags parameter value, if the clone_flags parameter indicates
Share instead of copy, increase the value of its counter count by 1, otherwise copy the relevant information content PCB needed by the new process. This place distinguishes between sys_fork () and sys_clone ().
2. The relevant kernel data structures that track the execution of the process must be set for the execution of the new process. Includes an array of tasks, a free-time list tarray_freelist, and an pidhash [] array.
This part completes the following contents:
Add a new process to the process list.
Add the new process to the pidhash hash table and increase the task count value.
Initialize the hardware context (TSS segment, LDT, and GDT) by copying the top and bottom of the parent process.
3. Start the scheduler so that the child process has the opportunity to run.
This section completes the following actions:
Set the new ready queue state TASK_RUNING, hang the new process into the ready queue, and restart the scheduler to make it run.
Return the PID of the child process to the parent process and set the child process to return a value of 0 from do_fork ().
The following is an analysis of the specific do_fork () function program code (this code is located in the kernel/fork.c file)
Int do_fork (unsigned long clone_flags,unsigned long stack_start, struct pt_regs * regs
Unsigned long stack_size)
{
Int retval
Struct task_struct * p
Struct completion vfork
Retval =-EPERM
If (clone_flags & CLONE_PID)
{
If (current- > pid)
Goto fork_out
}
Reval =-ENOMEM
P = alloc_task_struct (); / / allocate memory to establish the task_struct structure of the new process
If (! P)
Goto fork_out
* p = * current; / / copy the contents of the current process's task_struct structure to the PCB structure of the new process
Retval =-EAGAIN
/ / the following code assigns values to data members with different values in the task_struct structure of the parent and child processes
If (atomic_read (& p-> user- > processes) > = p-> RIM [RLIMIT _ NPROC] .rlim _ cur
& &! capable (CAP_SYS_ADMIN) & &! capable (CAP_SYS_RESOURCE)
Goto bad_fork_free
Atomic_inc (& p-> user- > _ _ count); / / count counter plus 1
Atomic_inc (& p-> user- > processes); / / number of processes plus 1
If (nr_threads > = max_threads)
Goto bad_fork_cleanup_count
Get_exec_domain (p-> exec_domain)
If (p-> binfmt & & p-> binfmt- > module)
_ _ MOD_INC_USE_COUNT (p-> binfmt- > module); / / Executable binfmt structure share count + 1
P-> did_exec = 0; / / the process is not executed
P-> swappable = 0; / / process cannot be swapped out
P-> state = TASK_UNINTERRUPTIBLE; / / set the process status
Copy_flags (clone_flags,p); / / copy process flag bit
P-> pid = get_pid (clone_flags); / / assign the process flag number to the new process
P-> run_list.next = NULL
P-> run_list.prev = NULL
P-> run_list.cptr = NULL
Init_waitqueue_head (& p-> wait_childexit); / / initialize the wait_childexit queue
P-> vfork_done = NULL
If (clone_flags & CLONE_VFORK) {
P-> vfork_done = & vfork
Init_completion & vfork)
}
Spin_lock_init (& p-> alloc_lock)
P-> sigpending = 0
Init_sigpending (& p-> pending)
P-> it_real_value = p-> it_virt_value = p-> it_prof_value = 0; / / initialize time data members
P-> it_real_incr = p-> it_virt_incr = p-> it_prof_incr = 0; / / initialize the timer structure
Init_timer (& p-> real_timer)
P-> real_timer.data = (unsigned long) p
P-> leader = 0
P-> tty_old_pgrp = 0
P-> times.tms_utime = p-> times.tms_stime = 0; / / various run times of the initialization process
P-> times.tms_cutime = p-> times.tms_cstime = 0
# ifdef CONFIG_SMP / / initialize symmetric processor members
{
Int i
P-> cpus_runnable = ~ 0UL
P-> processor = current- > processor
For (I = 0; I)
< smp_num_cpus ; i++ ) p->Per_cpu_utime [I] = p-> per_cpu_stime [I] = 0
Spin_lock_init (& p-> sigmask_lock)
}
# endif
P-> lock_depth =-1; / / Note: here-1 stands for no, indicating that the kernel is not locked during context switching.
P-> start_time = jiffies; / / set the start time of the process
INIT_LIST_HEAD (& p-> local_pages)
Retval =-ENOMEM
If (copy_files (clone_flags, p)) / / copy the files pointer of the parent process and share the files opened by the parent process
Goto bad_fork_cleanup
If (copy_fs (clone_flags, p)) / / copy the fs pointer of the parent process and share the file system of the parent process
Goto bad_fork_cleanup_files
If (copy_sighand (clone_flags, p)) / / the child process shares the signal processing function pointer of the parent process
Goto bad_fork_cleanup_fs
If (copy_mm (clone_flags, p))
Goto bad_fork_cleanup_mm; / / copy the mm information of the parent process and share the storage management information
Retval = copy_thread (0, clone_flags, stack_start, stack_size, p regs)
/ / initialize TSS, LDT and GDT items
If (retval)
Goto bad_fork_cleanup_mm
P-> semundo = NULL; / / initialize semaphore members
P-> prent_exec_id = p-self_exec_id
P-> swappable = 1; / / the memory pages occupied by the process can be swapped out
P-> exit_signal = clone_flag & CSIGNAL
P-> pdeatch_signal = 0; / / Note: this is the signal sent after the parent process dies.
P-> counter = (current- > counter + 1) > > 1; / / the dynamic priority of the process is set to half of the parent process. It should be noted that the bit operation is used here.
Current- > counter > > = 1
If (! current- > counter)
Current- > need_resched = 1; / / set the rescheduling flag, which is actually split into two processes, father and son.
Retval = p-> pid
P-> tpid = retval
INIT_LIST_HEAD (& p-> thread_group)
Write_lock_irq & tasklist_lock)
P-> p_opptr = current- > p_opptr
P-> p_pptr = current- > p_pptr
If (! (clone_flags & (CLONE_PARENT | CLONE_THREAD) {
P-> opptr = current
If (! (p-> ptrace & PT_PTRACED))
P-> p_pptr = current
}
If (clone_flags & CLONE_THREAD) {
P-> tpid = current- > tpid
List_add (& p-> thread_group,¤t- > thread_group)
}
SET_LINKS (p)
Hash_pid (p)
Nr_threads++
Write_unlock_irq & tasklist_lock)
If (p-> ptrace & PT_PTRACED)
Send_sig (SIGSTOP, p, 1)
Wake_up_process (p); / / add the new process to the run queue and start the scheduler to reschedule so that the new process gets the opportunity to run
+ + total_forks
If (clone_flags & CLONE_VFRK)
Wait_for_completion & vfork)
/ / the following is the error handling part
Fork_out:
Return retval
Bad_fork_cleanup_mm:
Exit_mm (p)
Bad_fork_cleanup_sighand:
Exit_sighand (p)
Bad_fork_cleanup_fs:
Exit_fs (p)
Bad_fork_cleanup_files:
Exit_files (p)
Bad_fork_cleanup:
Put_exec_domain (p-> exec_domain)
If (p-> binfmt & & p-> binfmt- > module)
_ _ MOD_DEC_USE_COUNT (p-> binfmt- > module)
Bad_fork_cleanup_count:
Atomic_dec (& p-> user- > processes)
Free_uid (p-> user)
Bad_fork_free:
Free_task_struct (p)
Goto fork_out
}
PS:
The code has been analyzed, and there are two aspects of experience:
First, the focus of this function is to understand the split part of the process, in which the value of returning pid twice is the top priority of understanding.
Second, although I have not advocated the extensive use of goto statements in programs, I have to admit that those Daniel's goto statements are just right to be used here. ^ _ ^
The above is how the fork function in linux creates a new process. Have you learned any knowledge or skills? If you want to learn more skills or enrich your knowledge reserve, you are welcome to follow the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.