当前位置:网站首页>PHP handwriting a perfect daemon

PHP handwriting a perfect daemon

2022-06-23 13:03:00 Thunder programming

Previously on

In the last issue, we learned the concept and usage of conversation in detail , conversation , Process group , Understanding the terminal is very important for the daemon described in this article , If you still don't understand the relevant concepts, I suggest you look at my previous conversation , Process group , Terminal article .

Basic concepts

Daemon (Daemon Process), That is to say Daemon process ( Elvish process ), yes Linux Background service process in . It is usually independent of the control terminal and periodically performs certain tasks or waits to handle certain events . And not associated with any control terminal , If you want a process not to be affected by user or interrupt or other changes , Then you must turn this process into a daemon .

Common daemons include the system log process syslogd、 web The server httpd、 Task planning daemon crond, database server mysqld etc. . Generally, it is used to d The ending name .

View system daemon commands ps -efj

Basic characteristics

Long life cycle [ Not necessary ], Generally, the operating system starts when it starts , Close when closing .

The daemon is not associated with the terminal , That is, they have no control terminal , So when the control terminal exits , Nor will it cause the daemon to exit .

Daemons run in the background , It won't occupy the terminal , The terminal can execute other commands `

The parent process of the daemons is 1 Process of no. , That is to say init process ;

stay Linux in , There are probably three ways to implement script backstage :

1 . Add a... After the command & Symbol , such as php task.php & . The disadvantage of this method is If terminal Terminal off , Whether it's normal shutdown or abnormal shutdown , This php The process will close as the terminal closes , The second is if there is echo perhaps print_r And so on , Will be output to the current terminal window .

2 . Use nohup command , such as nohup php task.php & . By default , In the code echo perhaps print_r The output text will be output to php Code sibling Directory nohup.out In file . If you use exit Command or close button and other normal means to close the terminal , The process will not be shut down , Still running in the background . But if the terminal encounters an abnormal exit or termination , The php The process also exits immediately . Essentially , It's not stable daemon programme .

3 . Use fork and setsid , I'm going to call it : *nix Solution

Creating daemons requires

1. Set file creation screen word umask(0)

The file creation mask word means that the corresponding bit when the file is created is masked . Due to the use fork The new child process created by the system call inherits the file creation mask of the parent process , This brings a lot of inconvenience to the subprocess to use the file . therefore , Set the file creation mask to 0, Can greatly enhance the flexibility of the daemons .

2. call fork, The parent process exits (exit);

If the daemon is as a simple shell Command initiated , Then the termination of the parent process makes shell It is considered that the order has been executed ; Ensure that the subprocess is not the leader of a process group , Why should we ensure that we are not the process team leader ? Because the process group leader calls setsid Creating a session will result in an error ;

3. Subprocess call setsid Function to create a session

Let me introduce you Linux Process and control terminal in , Relationship between login session and process group : A process belongs to a process group , Process group number (GID) Is the process number of the process leader (PID). A login session can contain multiple process groups . These process groups Share a control terminal . This control terminal is usually the login terminal of the creation process .

Control terminal , Login sessions and process groups are usually from Inherited from the parent process . Our goal is to get rid of them , Make it unaffected by them . The method is 2 Point based on , call setsid() Make the process the session leader :

setsid() After the call is successful , The process becomes a new conversation leader and a new process leader , And with the original login session and process group Out of the . Due to the exclusivity of the session process to the control terminal , The process is simultaneously with Control terminal disengages .

call setsid Yes 3 A role :
Let the process out of the control of the original session ;
Let the process out of the control of the original process group ;
Let the process get rid of the control of the original control terminal

4. Set the working directory of the daemon to the root directory chdir(“/”);

The working directory inherited from the parent process may be in a mounted file system . Because daemons usually exist until the system reboots , So if the current working directory of the daemon is in a mounted file system , This will prevent the file system from being unmounted .

5. Close some file descriptors 【 The standard input , standard output , The standard error 】

File descriptor : Used to identify a file . When you open an existing file or create a new file , The operating system will return this file descriptor . Some functions for subsequent operations on this file , Will use this file descriptor as a parameter .

Linux Three special file descriptors in , The numbers are 0,1,2:
0: The standard input [ keyboard ], The corresponding symbolic constant is called STDIN_FILENO
1: standard output [ The screen ], The corresponding symbolic constant is called STDOUT_FILENO
2: The standard error [ The screen ], The corresponding symbolic constant is called STDERR_FILENO

The process inherits the open file descriptor from the parent process that created it . If not closed , Will waste system resources , Causes the file system of the process to be unmounted and causes unexpected errors .

5. When calling setsid After the function , Generally, a child process is created , Let the session first process exit , Make sure that the process no longer controls the terminal

(1) Call once fork The role of :
for the first time fork The function of is to let shell That this order has been terminated , Do not hang on the terminal input , And for the later setsid service , Because of the call setsid The process of a function cannot be a process group leader , If you don't fork Out of child process , Then the parent process is the process group leader , Can't call setsid. When the child process calls setsid After the function , The child process is the session leader and the process group leader , And away from the control terminal , here , No matter how the control terminal operates , New processes will not receive any signals to make the process exit .
(2) The second time fork The role of :
Although the connection with the terminal is currently closed , However, the terminal may be opened by misoperation in the later stage .
Only the first session process can open the terminal device , That is to say, no more fork once , Then exit the parent process , Again fork The child process of continues to run as a daemon , This ensures that the daemon is no longer the first process of the session .
The second time is not necessary , It's optional .

Write a daemon

<?php

// 1.  Set file creation screen word 
umask(0);

// 2. fork  Subprocesses 
$pid = pcntl_fork();

if($pid > 0){
    
        print(" The parent process exits \n");
        exit(0);
}

//3.  Set the current child process as the first process of the session , Process leader , Disconnect from the terminal , Become a background process 
if(-1 === posix_setsid()){
    
        print("sid err \n");
}

// 4.  Set the working directory of the daemon to the root directory 
chdir("/");
// Has become a daemon ~\(≧▽≦)/~ La 
while(1){
    
echo "test".PHP_EOL;
sleep(2);
}

Save the file as daemon.php, then php daemon.php Executable files , Um. , The results of the implementation are somewhat strange , It is similar to the following figure :
 Insert picture description here
Even if you press Ctrl+C All useless , The terminal is constantly outputting test, The only way is to close the current terminal window and open it again , Why is that? , This involves the above-mentioned No 5 spot , You need to close the inherited standard output , Input , error , So our daemon Programs can no longer use the terminal window as the default standard output .

<?php

//  Set file creation screen word 
umask(0);

//  for the first time fork  Subprocesses 
$pid = pcntl_fork();

if($pid > 0){
    
        print(" The parent process exits \n");
        exit(0);
}
// The second time fork  Completely disconnect the control terminal 
$pid = pcntl_fork();
if($pid > 0){
    
	exit(0);// Let the session first process exit 
}

// Set the current child process as the first process of the session , Process leader , Disconnect from the terminal , Become a background process 
if(-1 === posix_setsid()){
    
        print("sid err \n");
}

//  Set the working directory of the daemon to the root directory 
chdir("/");

//  Turn off standard input , standard output , The standard error ,linux  The file descriptor is represented by a number in  0,1,2
fclose(STDIN);//0
fclose(STDOUT);//1
fclose(STDERR);//2
// When the above standard output is turned off , The standard input , After standard error , If you want to operate on the file later ( Like opening a file , write in , establish ) It returns a file descriptor from 0 Start , This may cause unknown exceptions 

// To avoid problems , We use output from directed to  /dev/null  Empty device files solve this problem , To reset 0,1,2  File descriptors are used in place of standard input , standard output , The standard error , Go to  /dev/null  Write data is discarded , In this way, data will not be output to the terminal .

$stdin = fopen("/dev/null",'a');
$stdout = fopen("/dev/null",'a');
$stderr = fopen("/dev/null", 'a');


// Has become a daemon ~\(≧▽≦)/~ La 
while(1){
    
echo "test".PHP_EOL;
sleep(2);
}


 Insert picture description here

  1. Empty equipment
    /dev/null : It's a special device file , It discards all data written into it ( Like black holes ) for example :echo “ Big thunder ” > /dev/null Output redirect file to black hole ( No output ).
    We usually input the standard input of the daemon 、 Standard output is redirected to an empty device ( Black holes ), This ensures that the daemon does not receive anything from the keyboard , And don't print the output to the screen .
原网站

版权声明
本文为[Thunder programming]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/174/202206231121087107.html