Các quy trình khác
Cho đến nay, chúng ta đã thảo luận về các quy trình, quá trình tạo ra nó, quy trình mẹ và con, v.v. Cuộc thảo luận sẽ không đầy đủ nếu không thảo luận về các quy trình liên quan khác, chẳng hạn như quy trình Orphan, quy trình Zombie và quy trình Daemon.
Quá trình mồ côi
Như được chỉ ra trong tên, mồ côi ngụ ý quá trình không cha mẹ. Khi chúng tôi chạy một chương trình hoặc ứng dụng, quy trình cha của ứng dụng là shell. Khi chúng ta tạo một tiến trình bằng fork (), tiến trình mới được tạo là tiến trình con và tiến trình tạo ra con là tiến trình mẹ. Đổi lại, tiến trình cha của quá trình này là shell. Tất nhiên, cha của tất cả các quy trình là quy trình init (ID quy trình → 1).
Trên đây là một kịch bản thông thường, tuy nhiên, điều gì sẽ xảy ra nếu process cha thoát ra trước process con. Kết quả là, tiến trình con bây giờ trở thành tiến trình mồ côi. Vậy còn cha mẹ của nó thì sao, cha mẹ mới của nó là cha của tất cả các tiến trình, không là gì khác ngoài tiến trình init (Process ID - 1).
Hãy để chúng tôi thử và hiểu điều này bằng cách sử dụng ví dụ sau.
/ * Tên tệp: 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;
}
Các bước biên dịch và thực hiện
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
Quá trình xác sống
Nói một cách dễ hiểu, giả sử rằng bạn có hai quy trình, đó là quy trình cha và quy trình con. Quy trình cha có trách nhiệm đợi quy trình con và sau đó xóa mục nhập quy trình con khỏi bảng quy trình. Điều gì sẽ xảy ra nếu process cha không sẵn sàng chờ process con, và trong khi đó process con hoàn thành công việc và thoát ra? Bây giờ, tiến trình con sẽ trở thành tiến trình thây ma. Tất nhiên, tiến trình zombie được dọn dẹp sau khi tiến trình mẹ sẵn sàng.
Hãy để chúng tôi hiểu điều này với sự trợ giúp của một ví dụ.
/ * Tên tệp: 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;
}
Các bước biên dịch và thực hiện
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
Quy trình Daemon
Nói một cách dễ hiểu, tiến trình không có bất kỳ trình bao hoặc thiết bị đầu cuối liên quan nào được gọi là quy trình daemon. Tại sao điều này là cần thiết? Đây là các quy trình chạy trong nền để thực hiện các hành động theo các khoảng thời gian được xác định trước và cũng phản hồi các sự kiện nhất định. Quá trình daemon không được có bất kỳ tương tác nào của người dùng, vì nó chạy như một quá trình nền.
Các quy trình nền Linux nội bộ thường kết thúc bằng ký tự “d” như Kernel Daemons (ksoftirqd, kblockd, kswapd, v.v.), Daemons in (cupd, lpd, v.v.), Daemons dịch vụ tệp (smbd, nmbd, v.v.) , Daemon cơ sở dữ liệu quản trị (ypbind, ypserv, v.v.), Daemon thư điện tử (sendmail, popd, smtpd, v.v.), Daemons đăng nhập từ xa và thực thi lệnh (sshd, in.telnetd, v.v.), Daemon khởi động và cấu hình (dhcpd , udevd, v.v.), init process (init), cron daemon, atd daemon, v.v.
Bây giờ chúng ta hãy xem cách tạo một quy trình daemon. Sau đây là các bước -
Step 1- Tạo quy trình con. Bây giờ chúng ta có hai quy trình - quy trình mẹ và quy trình con
Thông thường, thứ bậc quy trình là VỎ → QUY TRÌNH PHỤ HUYNH → QUY TRÌNH CON
Step 2- Chấm dứt tiến trình cha bằng cách thoát. Tiến trình con bây giờ trở thành tiến trình mồ côi và được tiếp quản bởi tiến trình init.
Bây giờ, hệ thống phân cấp là QUY TRÌNH INIT → QUÁ TRÌNH TRẺ EM
Step 3- Việc gọi lệnh gọi hệ thống setsid () tạo ra một phiên mới, nếu quá trình gọi không phải là nhóm trưởng quá trình. Bây giờ quá trình gọi trở thành nhóm trưởng của phiên mới. Quy trình này sẽ là quy trình duy nhất trong nhóm quy trình mới này và trong phiên mới này.
Step 4 - Đặt ID nhóm quy trình và ID phiên thành PID của quy trình gọi.
Step 5 - Đóng các bộ mô tả tệp mặc định (đầu vào tiêu chuẩn, đầu ra tiêu chuẩn và lỗi tiêu chuẩn) của quá trình vì thiết bị đầu cuối và trình bao giờ đã bị ngắt kết nối khỏi ứng dụng.
/ * Tên tệp: 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