setpgid
POSIX সি প্রক্রিয়া গ্রুপ ন্যূনতম উদাহরণ
অন্তর্নিহিত এপিআই এর একটি ন্যূনতম চলমান উদাহরণ দিয়ে বোঝা আরও সহজ হতে পারে।
এটি চিত্রিত করে যে কীভাবে সিগন্যালটি শিশুকে প্রেরণ করা হয়, যদি শিশু তার প্রক্রিয়া গোষ্ঠীটি পরিবর্তন না করে setpgid
।
main.c
#define _XOPEN_SOURCE 700
#include <assert.h>
#include <signal.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
volatile sig_atomic_t is_child = 0;
void signal_handler(int sig) {
char parent_str[] = "sigint parent\n";
char child_str[] = "sigint child\n";
signal(sig, signal_handler);
if (sig == SIGINT) {
if (is_child) {
write(STDOUT_FILENO, child_str, sizeof(child_str) - 1);
} else {
write(STDOUT_FILENO, parent_str, sizeof(parent_str) - 1);
}
}
}
int main(int argc, char **argv) {
pid_t pid, pgid;
(void)argv;
signal(SIGINT, signal_handler);
signal(SIGUSR1, signal_handler);
pid = fork();
assert(pid != -1);
if (pid == 0) {
is_child = 1;
if (argc > 1) {
/* Change the pgid.
* The new one is guaranteed to be different than the previous, which was equal to the parent's,
* because `man setpgid` says:
* > the child has its own unique process ID, and this PID does not match
* > the ID of any existing process group (setpgid(2)) or session.
*/
setpgid(0, 0);
}
printf("child pid, pgid = %ju, %ju\n", (uintmax_t)getpid(), (uintmax_t)getpgid(0));
assert(kill(getppid(), SIGUSR1) == 0);
while (1);
exit(EXIT_SUCCESS);
}
/* Wait until the child sends a SIGUSR1. */
pause();
pgid = getpgid(0);
printf("parent pid, pgid = %ju, %ju\n", (uintmax_t)getpid(), (uintmax_t)pgid);
/* man kill explains that negative first argument means to send a signal to a process group. */
kill(-pgid, SIGINT);
while (1);
}
গিটহাব উজানের দিকে ।
এর সাথে সংকলন:
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -Wpedantic -o setpgid setpgid.c
ছাড়া চালাও setpgid
কোনও সিএলআই আর্গুমেন্ট ছাড়া, setpgid
সম্পন্ন করা হয় না:
./setpgid
সম্ভাব্য ফলাফল:
child pid, pgid = 28250, 28249
parent pid, pgid = 28249, 28249
sigint parent
sigint child
এবং প্রোগ্রাম স্থগিত।
যেমন আমরা দেখতে পাচ্ছি, উভয় প্রক্রিয়ার পিজিডিটি একইরকম, যেমন এটি উত্তরাধিকারসূত্রে প্রাপ্ত হয় fork
।
তারপরে আপনি যখনই আঘাত করবেন:
Ctrl + C
এটি আবার ফলাফল:
sigint parent
sigint child
এটি কীভাবে দেখায়:
- এর সাথে একটি সম্পূর্ণ প্রক্রিয়া গোষ্ঠীতে একটি সংকেত প্রেরণ করতে
kill(-pgid, SIGINT)
- টার্মিনালের Ctrl + C ডিফল্টরূপে পুরো প্রক্রিয়া গোষ্ঠীতে একটি কিল পাঠায়
উভয় প্রক্রিয়াতে একটি পৃথক সিগন্যাল প্রেরণ করে প্রোগ্রামটি প্রস্থান করুন, উদাহরণস্বরূপ SIGQUIT দিয়ে Ctrl + \
।
সাথে চালাও setpgid
আপনি যদি কোনও যুক্তি দিয়ে চালনা করেন, যেমন:
./setpgid 1
তারপরে বাচ্চা তার পিজিডি পরিবর্তন করে এবং এখন কেবলমাত্র বাবা-মার কাছ থেকে প্রতিবারই একক সিগিন্ট মুদ্রিত হয়:
child pid, pgid = 16470, 16470
parent pid, pgid = 16469, 16469
sigint parent
এবং এখন, আপনি যখনই আঘাত করবেন:
Ctrl + C
কেবল পিতামাতাই সিগন্যালটি পান:
sigint parent
আপনি এখনও একটি সিকিউইটি দিয়ে পূর্বের মতো পিতামাতাকে হত্যা করতে পারেন:
Ctrl + \
তবে সন্তানের এখন আলাদা আলাদা পিজিআইডি রয়েছে, এবং সেই সংকেতটি পান না! এটি থেকে দেখা যায়:
ps aux | grep setpgid
আপনাকে এটিকে স্পষ্টভাবে হত্যা করতে হবে:
kill -9 16470
এটি সিগন্যাল গোষ্ঠী কেন বিদ্যমান তা পরিষ্কার করে দেয়: অন্যথায় আমরা সমস্ত সময় ম্যানুয়ালি পরিষ্কার করার জন্য একগুচ্ছ প্রক্রিয়াগুলি পেয়ে যাব।
উবুন্টু 18.04 এ পরীক্ষিত।