About daemon and botnets

Source: Internet
Author: User

The first commercial service maintained in used two fork daemon practices. I saw many posts and Some UNIX books on the internet two days ago, I think it makes sense to generate a daemon after one fork. But what is the purpose of an additional fork?

Process is task. Check the data structure task_struct of the process maintained in the kernel. There are two members:

struct task_struct {volatile long state;int exit_state;...}

Let's take a look at the values in include/Linux/sched. h:

#define TASK_RUNNING0#define TASK_INTERRUPTIBLE1#define TASK_UNINTERRUPTIBLE2#define __TASK_STOPPED4#define __TASK_TRACED8/* in tsk->exit_state */#define EXIT_ZOMBIE16#define EXIT_DEAD32/* in tsk->state again */#define TASK_DEAD64#define TASK_WAKEKILL128#define TASK_WAKING256#define TASK_STATE_MAX512

We can see that in addition to running, interuptible, uninterruptible, and stop states that everyone understands, there is also a zombie state. What is the status?

This is because all processes in Linux belong to a tree. The root node of the tree is the INIT process started at the end of Linux system initialization. The PID of the process is 1, all other processes are their children. In addition to init, any process must have its parent process, and the parent process will be responsible for allocating (fork) and revoking (wait4) The process resources it applies. This tree-like relationship is also robust. When a process is still running, its parent process exits, but this process does not become an orphan process, because Linux has a mechanism, the INIT process takes over it and becomes its parent process. This is also the origin of the daemon process, because one of the requirements of the daemon process is that it wants init to become the parent process of the daemon process.

If a process terminates itself, it will enter the zombie state after calling exit to clear related content files and other resources, and its parent process will call wait4 to recycle the task_struct, however, if the parent process has never called wait4 to release the task_struct of the child process, the problem arises. Who will recycle this task_struct? No one will ever be there unless the parent process is terminated and the INIT process takes over the zombie process, and then wait4 is called to recycle the process descriptor. If the parent process is running all the time, zombie will occupy the system resources forever and use kill to send any semaphores. This is terrible because numerous zombie processes may occur on the server, causing the machine to crash.

Let's take a look at the kernel code. When the process exits, it executes sys_exit (the main function in the C program will be executed), and it will call do_exit. do_exit first clears the resources used by the process, and then calls the exit_notify method, set the process to the zombie state of the zombie, decide whether to use the INIT process as the parent process of the current process, and finally notify the parent process of the current process:

Kernel/exit. c

static void exit_notify(struct task_struct *tsk){int state;struct task_struct *t;struct list_head ptrace_dead, *_p, *_n;if (signal_pending(tsk) && !tsk->signal->group_exit    && !thread_group_empty(tsk)) {/* * This occurs when there was a race between our exit * syscall and a group signal choosing us as the one to * wake up.  It could be that we are the only thread * alerted to check for pending signals, but another thread * should be woken now to take the signal since we will not. * Now we'll wake all the threads in the group just to make * sure someone gets all the pending signals. */read_lock(&tasklist_lock);spin_lock_irq(&tsk->sighand->siglock);for (t = next_thread(tsk); t != tsk; t = next_thread(t))if (!signal_pending(t) && !(t->flags & PF_EXITING)) {recalc_sigpending_tsk(t);if (signal_pending(t))signal_wake_up(t, 0);}spin_unlock_irq(&tsk->sighand->siglock);read_unlock(&tasklist_lock);}write_lock_irq(&tasklist_lock);/* * This does two things: *   * A.  Make init inherit all the child processes * B.  Check to see if any process groups have become orphaned *as a result of our exiting, and if they have any stopped *jobs, send them a SIGHUP and then a SIGCONT.  (POSIX 3.2.2.2) */INIT_LIST_HEAD(&ptrace_dead);forget_original_parent(tsk, &ptrace_dead);BUG_ON(!list_empty(&tsk->children));BUG_ON(!list_empty(&tsk->ptrace_children));/* * Check to see if any process groups have become orphaned * as a result of our exiting, and if they have any stopped * jobs, send them a SIGHUP and then a SIGCONT.  (POSIX 3.2.2.2) * * Case i: Our father is in a different pgrp than we are * and we were the only connection outside, so our pgrp * is about to become orphaned. */ t = tsk->real_parent;if ((process_group(t) != process_group(tsk)) &&    (t->signal->session == tsk->signal->session) &&    will_become_orphaned_pgrp(process_group(tsk), tsk) &&    has_stopped_jobs(process_group(tsk))) {__kill_pg_info(SIGHUP, (void *)1, process_group(tsk));__kill_pg_info(SIGCONT, (void *)1, process_group(tsk));}/* Let father know we died  * * Thread signals are configurable, but you aren't going to use * that to send signals to arbitary processes.  * That stops right now. * * If the parent exec id doesn't match the exec id we saved * when we started then we know the parent has changed security * domain. * * If our self_exec id doesn't match our parent_exec_id then * we have changed execution domain as these two values started * the same after a fork. * */if (tsk->exit_signal != SIGCHLD && tsk->exit_signal != -1 &&    ( tsk->parent_exec_id != t->self_exec_id  ||      tsk->self_exec_id != tsk->parent_exec_id)    && !capable(CAP_KILL))tsk->exit_signal = SIGCHLD;/* If something other than our normal parent is ptracing us, then * send it a SIGCHLD instead of honoring exit_signal.  exit_signal * only has special meaning to our real parent. */if (tsk->exit_signal != -1 && thread_group_empty(tsk)) {int signal = tsk->parent == tsk->real_parent ? tsk->exit_signal : SIGCHLD;do_notify_parent(tsk, signal);} else if (tsk->ptrace) {do_notify_parent(tsk, SIGCHLD);}state = EXIT_ZOMBIE;if (tsk->exit_signal == -1 && tsk->ptrace == 0)state = EXIT_DEAD;tsk->exit_state = state;/* * Clear these here so that update_process_times() won't try to deliver * itimer, profile or rlimit signals to this task while it is in late exit. */tsk->it_virt_value = 0;tsk->it_prof_value = 0;write_unlock_irq(&tasklist_lock);list_for_each_safe(_p, _n, &ptrace_dead) {list_del_init(_p);t = list_entry(_p,struct task_struct,ptrace_list);release_task(t);}/* If the process is dead, release it - nobody will wait for it */if (state == EXIT_DEAD)release_task(tsk);/* PF_DEAD causes final put_task_struct after we schedule. */preempt_disable();tsk->flags |= PF_DEAD;}

You can see that the comments of this kernel code are very comprehensive. The forget_original_parent function will reset all child processes of the process to the parent process and hand it over to the INIT process to take over.

Let's look back at why the daemon has to fork twice. It is assumed that after the parent process generates a daemon, there is something to do. Its life meaning is not just to generate a daemon. In this way, if the parent process fork creates a daemon at a time, and then continues to do other things, the daemon continues to run, but the parent process does not exit normally. If the daemon exits due to normal or abnormal reasons, it will become the zombie process.

What if fork is used twice? The parent process first fork out a son process, and then fork out of the son process as a daemon process, then the son process immediately exits, the daemon process is taken over by the INIT process, in this way, no matter what the parent process does or how blocked it is, it is irrelevant to the daemon process. Therefore, fork's two daemon processes are very secure, avoiding the possibility of zombie processes.

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.