กระบวนการอื่น ๆ
จนถึงตอนนี้เราได้พูดคุยเกี่ยวกับกระบวนการการสร้างกระบวนการแม่และลูก ฯลฯ การสนทนาจะไม่สมบูรณ์หากไม่พูดถึงกระบวนการอื่น ๆ ที่เกี่ยวข้องเช่นกระบวนการเด็กกำพร้ากระบวนการซอมบี้และกระบวนการภูต
กระบวนการเด็กกำพร้า
ตามที่ระบุโดยชื่อเด็กกำพร้าหมายถึงกระบวนการที่ไม่มีผู้ปกครอง เมื่อเรารันโปรแกรมหรือแอ็พพลิเคชันกระบวนการหลักสำหรับแอ็พพลิเคชันคือเชลล์ เมื่อเราสร้างกระบวนการโดยใช้ fork () กระบวนการที่สร้างขึ้นใหม่คือกระบวนการลูกและกระบวนการที่สร้างลูกคือกระบวนการแม่ ในทางกลับกันกระบวนการหลักของสิ่งนี้คือเชลล์ แน่นอนว่าพาเรนต์ของกระบวนการทั้งหมดคือกระบวนการเริ่มต้น (Process ID → 1)
ข้างต้นเป็นสถานการณ์ปกติอย่างไรก็ตามจะเกิดอะไรขึ้นถ้ากระบวนการหลักออกก่อนกระบวนการย่อย ผลลัพธ์คือตอนนี้กระบวนการย่อยกลายเป็นกระบวนการเด็กกำพร้า แล้วสิ่งที่เกี่ยวกับพาเรนต์พาเรนต์ใหม่คือพาเรนต์ของโปรเซสทั้งหมดซึ่งไม่มีอะไรเลยนอกจากกระบวนการเริ่มต้น (ID กระบวนการ - 1)
ให้เราลองทำความเข้าใจโดยใช้ตัวอย่างต่อไปนี้
/ * ชื่อไฟล์: orphan_process.c * /
#include<stdio.h>
#include<stdlib.h>
int main() {
int pid;
system("ps -f");
pid = fork();
if (pid == 0) {
printf("Child: pid is %d and ppid is %d\n",getpid(),getppid());
sleep(5);
printf("Child: pid is %d and ppid is %d\n",getpid(),getppid());
system("ps -f");
} else {
printf("Parent: pid is %d and ppid is %d\n",getpid(),getppid());
sleep(2);
exit(0);
}
return 0;
}
ขั้นตอนการรวบรวมและดำเนินการ
UID PID PPID C STIME TTY TIME CMD
4581875 180558 0 0 09:19 ? 00:00:00 sh -c cd /home/cg/root/4581875;
timeout 10s main
4581875 180564 180558 0 09:19 ? 00:00:00 timeout 10s main
4581875 180565 180564 0 09:19 ? 00:00:00 main
4581875 180566 180565 0 09:19 ? 00:00:00 ps -f
Parent: pid is 180565 and ppid is 180564
UID PID PPID C STIME TTY TIME CMD
4581875 180567 0 0 09:19 ? 00:00:00 main
4581875 180820 180567 0 09:19 ? 00:00:00 ps -f
Child: pid is 180567 and ppid is 180565
Child: pid is 180567 and ppid is 0
กระบวนการซอมบี้
พูดง่ายๆสมมติว่าคุณมีสองกระบวนการคือกระบวนการหลักและกระบวนการย่อย เป็นความรับผิดชอบของโปรเซสพาเรนต์ในการรอโปรเซสลูกจากนั้นล้างรายการโปรเซสลูกจากตารางกระบวนการ จะเกิดอะไรขึ้นถ้ากระบวนการหลักไม่พร้อมที่จะรอกระบวนการลูกและในระหว่างนี้กระบวนการลูกจะทำงานเสร็จและออกไป ตอนนี้กระบวนการเด็กจะกลายเป็นกระบวนการซอมบี้ แน่นอนกระบวนการซอมบี้จะถูกล้างหลังจากกระบวนการหลักพร้อมแล้ว
ให้เราเข้าใจสิ่งนี้ด้วยความช่วยเหลือของตัวอย่าง
/ * ชื่อไฟล์: zombie_process.c * /
#include<stdio.h>
#include<stdlib.h>
int main() {
int pid;
pid = fork();
if (pid == 0) {
system("ps -f");
printf("Child: pid is %d and ppid is %d\n",getpid(),getppid());
exit(0);
} else {
printf("Parent: pid is %d and ppid is %d\n",getpid(),getppid());
sleep(10);
system("ps aux|grep Z");
}
return 0;
}
ขั้นตอนการรวบรวมและดำเนินการ
UID PID PPID C STIME TTY TIME CMD
4581875 184946 0 0 09:20 ? 00:00:00 sh -c cd /home/cg/root/4581875;
timeout 10s main
4581875 184952 184946 0 09:20 ? 00:00:00 timeout 10s main
4581875 184953 184952 0 09:20 ? 00:00:00 main
4581875 184954 184953 0 09:20 ? 00:00:00 main
4581875 184955 184954 0 09:20 ? 00:00:00 ps -f
Child: pid is 184954 and ppid is 184953
กระบวนการ Daemon
กล่าวง่ายๆคือกระบวนการที่ไม่มีเชลล์หรือเทอร์มินัลที่เกี่ยวข้องเรียกว่ากระบวนการดีมอน ทำไมจึงจำเป็น? นี่คือกระบวนการที่ทำงานอยู่เบื้องหลังเพื่อดำเนินการตามช่วงเวลาที่กำหนดไว้ล่วงหน้าและตอบสนองต่อเหตุการณ์บางอย่าง กระบวนการ daemon ไม่ควรมีการโต้ตอบกับผู้ใช้เนื่องจากรันเป็นกระบวนการเบื้องหลัง
กระบวนการภายใน Linux daemon มักจะลงท้ายด้วยตัวอักษร“ d” เช่น Kernel Daemons (ksoftirqd, kblockd, kswapd ฯลฯ ), Printing Daemons (cupsd, lpd ฯลฯ ), File Service Daemons (smbd, nmbd เป็นต้น) , daemons ฐานข้อมูลการดูแลระบบ (ypbind, ypserv ฯลฯ ), Daemons ไปรษณีย์อิเล็กทรอนิกส์ (sendmail, popd, smtpd ฯลฯ ), Remote Login และ Command Execution Daemons (sshd, in.telnetd ฯลฯ ), Booting and Configuration Daemons (dhcpd , udevd ฯลฯ ), กระบวนการเริ่มต้น (init), cron daemon, atd daemon ฯลฯ
ตอนนี้ให้เราดูวิธีสร้างกระบวนการภูต ต่อไปนี้เป็นขั้นตอน -
Step 1- สร้างกระบวนการลูก ตอนนี้เรามีสองกระบวนการ - กระบวนการหลักและกระบวนการลูก
โดยปกติลำดับชั้นของกระบวนการคือ SHELL → PARENT PROCESS → CHILD PROCESS
Step 2- ยุติกระบวนการหลักโดยการออก ตอนนี้กระบวนการย่อยกลายเป็นกระบวนการเด็กกำพร้าและถูกยึดครองโดยกระบวนการเริ่มต้น
ตอนนี้ลำดับชั้นคือ INIT PROCESS → CHILD PROCESS
Step 3- การเรียกการเรียกระบบ setsid () จะสร้างเซสชันใหม่หากกระบวนการเรียกไม่ใช่หัวหน้ากลุ่มกระบวนการ ตอนนี้กระบวนการโทรกลายเป็นผู้นำกลุ่มของเซสชันใหม่ กระบวนการนี้จะเป็นกระบวนการเดียวในกลุ่มกระบวนการใหม่นี้และในเซสชันใหม่นี้
Step 4 - ตั้งค่า ID กลุ่มกระบวนการและรหัสเซสชันเป็น PID ของกระบวนการโทร
Step 5 - ปิดตัวอธิบายไฟล์เริ่มต้น (อินพุตมาตรฐานเอาต์พุตมาตรฐานและข้อผิดพลาดมาตรฐาน) ของกระบวนการเนื่องจากเทอร์มินัลและเชลล์ถูกตัดการเชื่อมต่อจากแอปพลิเคชัน
/ * ชื่อไฟล์: daemon_test.c * /
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>
#include<string.h>
int main(int argc, char *argv[]) {
pid_t pid;
int counter;
int fd;
int max_iterations;
char buffer[100];
if (argc < 2)
max_iterations = 5;
else {
max_iterations = atoi(argv[1]);
if ( (max_iterations <= 0) || (max_iterations > 20) )
max_iterations = 10;
}
pid = fork();
// Unable to create child process
if (pid < 0) {
perror("fork error\n");
exit(1);
}
// Child process
if (pid == 0) {
fd = open("/tmp/DAEMON.txt", O_WRONLY|O_CREAT|O_TRUNC, 0644);
if (fd == -1) {
perror("daemon txt file open error\n");
return 1;
}
printf("Child: pid is %d and ppid is %d\n", getpid(), getppid());
printf("\nChild process before becoming session leader\n");
sprintf(buffer, "ps -ef|grep %s", argv[0]);
system(buffer);
setsid();
printf("\nChild process after becoming session leader\n");
sprintf(buffer, "ps -ef|grep %s", argv[0]);
system(buffer);
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
} else {
printf("Parent: pid is %d and ppid is %d\n", getpid(), getppid());
printf("Parent: Exiting\n");
exit(0);
}
// Executing max_iteration times
for (counter = 0; counter < max_iterations; counter++) {
sprintf(buffer, "Daemon process: pid is %d and ppid is %d\n", getpid(), getppid());
write(fd, buffer, strlen(buffer));
sleep(2);
}
strcpy(buffer, "Done\n");
write(fd, buffer, strlen(buffer));
// Can't print this as file descriptors are already closed
printf("DoneDone\n");
close(fd);
return 0;
}
Parent: pid is 193524 and ppid is 193523
Parent: Exiting
4581875 193525 0 0 09:23 ? 00:00:00 main
4581875 193526 193525 0 09:23 ? 00:00:00 sh -c ps -ef|grep main
4581875 193528 193526 0 09:23 ? 00:00:00 grep main
4581875 193525 0 0 09:23 ? 00:00:00 main
4581875 193529 193525 0 09:23 ? 00:00:00 sh -c ps -ef|grep main
4581875 193531 193529 0 09:23 ? 00:00:00 grep main