কিভাবে এক ক্যাচ করে Ctrl+ + Cসি?
কিভাবে এক ক্যাচ করে Ctrl+ + Cসি?
উত্তর:
একটি সিগন্যাল হ্যান্ডলার সহ।
এখানে bool
ব্যবহৃত একটি উল্টানো একটি সাধারণ উদাহরণ main()
:
#include <signal.h>
static volatile int keepRunning = 1;
void intHandler(int dummy) {
keepRunning = 0;
}
// ...
int main(void) {
signal(SIGINT, intHandler);
while (keepRunning) {
// ...
জুন 2017 এ সম্পাদনা করুন : যার জন্য এটি উদ্বিগ্ন হতে পারে, বিশেষত যারা এই উত্তরটি সম্পাদনা করার জন্য অযৌক্তিক তাগিদ সহ। দেখুন, আমি এই উত্তরটি সাত বছর আগে লিখেছি । হ্যাঁ, ভাষার মান পরিবর্তন হয়। আপনি যদি সত্যিই বিশ্বের উন্নত করতে চান তবে দয়া করে আপনার নতুন উত্তর যুক্ত করুন তবে আমার মতো করুন। যেহেতু উত্তরটিতে আমার নাম রয়েছে, আমি এটি আমার শব্দগুলিকেও ধারণ করতে পছন্দ করব। ধন্যবাদ.
bool volatile keepRunning = true;
100% নিরাপদ হওয়া উচিত । সংকলক keepRunning
একটি রেজিস্টারে ক্যাশে নিখরচায় রয়েছে এবং উদ্বায়ী এটিকে প্রতিরোধ করবে। অনুশীলনে এটি সম্ভবত অস্থায়ী কীওয়ার্ড ব্যতীত কাজ করতে পারে যখন যখন লুপ কমপক্ষে একটি অ-ইনলাইন ফাংশন কল করে।
sig_atomic_t
বা atomic_bool
টাইপ করব। আমি কেবল সেটিকে মিস করেছি। এখন, যেহেতু আমরা কথা বলছি: আপনি কি আমার সর্বশেষ সম্পাদনাটি রোলব্যাক করতে চান? কোনও শক্ত অনুভূতিই এটি আপনার দৃষ্টিকোণ থেকে পুরোপুরি
এখানে চেক করুন:
দ্রষ্টব্য: স্পষ্টতই, হ্যান্ডলারটি কীভাবে সেটআপ করা যায় সে সম্পর্কে এটি ব্যাখ্যা করার একটি সহজ উদাহরণ CtrlC, তবে সর্বদা নিয়ম রয়েছে যা অন্য কোনও কিছু ভঙ্গ না করার জন্য মেনে চলতে হবে। নীচের মন্তব্য পড়ুন।
উপরে থেকে নমুনা কোড:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
void INThandler(int);
int main(void)
{
signal(SIGINT, INThandler);
while (1)
pause();
return 0;
}
void INThandler(int sig)
{
char c;
signal(sig, SIG_IGN);
printf("OUCH, did you hit Ctrl-C?\n"
"Do you really want to quit? [y/n] ");
c = getchar();
if (c == 'y' || c == 'Y')
exit(0);
else
signal(SIGINT, INThandler);
getchar(); // Get new line character
}
int main
একটি যথাযথ জিনিস, gcc
এবং অন্যান্য সংকলকগণ 1990 এর দশক থেকে এটি সঠিকভাবে চলমান প্রোগ্রামগুলিতে সংকলন করে। এখানে বেশ ভালভাবে ব্যাখ্যা করা হয়েছে: eskimo.com/~scs/readings/voidmain.960823.html - এটি মূলত একটি "বৈশিষ্ট্য", আমি এটি এর মতো নিই।
ইউএন * এক্স প্ল্যাটফর্ম সম্পর্কিত সংযোজন।
signal(2)
জিএনইউ / লিনাক্সের ম্যান পেজ অনুসারে , আচরণটি signal
যেমন আচরণের মতো বহনযোগ্য নয় তেমন sigaction
:
সিগন্যালের () ব্যবহারটি ইউনিক্স সংস্করণে পৃথক হয়ে থাকে এবং লিনাক্সের বিভিন্ন সংস্করণেও historতিহাসিকভাবে বৈচিত্র রয়েছে। এর ব্যবহার এড়িয়ে চলুন: পরিবর্তে সিগিয়েশন (2) ব্যবহার করুন।
সিস্টেম ভিতে, সিস্টেমটি সিগন্যালের আরও উদাহরণগুলির সরবরাহ সরবরাহকে অবরুদ্ধ করে না এবং একটি সংকেতের বিতরণ হ্যান্ডলারটিকে ডিফল্টরূপে পুনরায় সেট করে। বিএসডিতে শব্দার্থবিজ্ঞানের পরিবর্তন ঘটে।
ডির্ক এডেলবুয়েটেলের sigaction
পরিবর্তে পূর্ববর্তী উত্তরের নিম্নলিখিত পরিবর্তনের ব্যবহারগুলি পরিবর্তে signal
:
#include <signal.h>
#include <stdlib.h>
static bool keepRunning = true;
void intHandler(int) {
keepRunning = false;
}
int main(int argc, char *argv[]) {
struct sigaction act;
act.sa_handler = intHandler;
sigaction(SIGINT, &act, NULL);
while (keepRunning) {
// main loop
}
}
অথবা আপনি টার্মিনালটি কাঁচা মোডে রাখতে পারেন:
struct termios term;
term.c_iflag |= IGNBRK;
term.c_iflag &= ~(INLCR | ICRNL | IXON | IXOFF);
term.c_lflag &= ~(ICANON | ECHO | ECHOK | ECHOE | ECHONL | ISIG | IEXTEN);
term.c_cc[VMIN] = 1;
term.c_cc[VTIME] = 0;
tcsetattr(fileno(stdin), TCSANOW, &term);
এখন ব্যবহার করে Ctrl+ Cকীস্ট্রোকগুলি পড়া সম্ভব হবে fgetc(stdin)
। এটি ব্যবহার করা থেকে সাবধান থাকুন কারণ আপনি সাধারণত Ctrl++ Z, Ctrl+ Q, Ctrl+ Sইত্যাদি পারেন না।
একটি ফাঁদ সেট আপ করুন (আপনি একটি হ্যান্ডলারের সাহায্যে কয়েকটি সিগন্যাল ফাঁদে ফেলতে পারেন):
সিগন্যাল (SIGQUIT, আমার_হ্যান্ডলার); সিগন্যাল (SIGINT, আমার_হ্যান্ডলার);
আপনি চাইলে সিগন্যালটি পরিচালনা করুন, তবে সীমাবদ্ধতা এবং গোটচাস সম্পর্কে সচেতন থাকুন:
অকার্যকর আমার_হ্যান্ডলার (ইন সিগ) { / * আপনার কোড এখানে। * / }
@ পিটার ভারো ড र्कের উত্তর আপডেট করেছেন, কিন্তু ডার্ক এই পরিবর্তনটি প্রত্যাখ্যান করেছেন। পিটারের নতুন উত্তরটি এখানে:
যদিও উপরের স্নিপেটটি সঠিক c89উদাহরণস্বরূপ, যদি আরও সম্ভব হয় তবে যদি সম্ভব হয় তবে পরবর্তী মানগুলির দ্বারা সরবরাহ করা আরও আধুনিক ধরণের এবং গ্যারান্টি ব্যবহার করা উচিত। সুতরাং, এখানে যারা সন্ধান করছেন তাদের জন্য এখানে একটি নিরাপদ এবং আধুনিক বিকল্পC99 এবং C11 অনুসারে বাস্তবায়ন:
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
static volatile sig_atomic_t keep_running = 1;
static void sig_handler(int _)
{
(void)_;
keep_running = 0;
}
int main(void)
{
signal(SIGINT, sig_handler);
while (keep_running)
puts("Still running...");
puts("Stopped by signal `SIGINT'");
return EXIT_SUCCESS;
}
সি 11 স্ট্যান্ডার্ড: 7.14§2 শিরোনাম
<signal.h>
একটি প্রকার ঘোষণা করে ...sig_atomic_t
যা অণু সত্তা হিসাবে অ্যাকসন ক্রোনার উপস্থিতিতে এমনকি কোনও অণু সত্তা হিসাবে অ্যাক্সেস করা যায় এমন কোনও সামগ্রীর (সম্ভবত উদ্বায়ী-যোগ্য) পূর্ণসংখ্যা টাইপ।
উপরন্তু:
সি 11 স্ট্যান্ডার্ড: 7.14.1.1§§5 যদি সিগন্যালটি
abort
বাraise
ফাংশন কল করার ফলাফল ব্যতীত অন্য কোনও ঘটনা ঘটে থাকে তবে সিগন্যাল হ্যান্ডলার এমন কোনও বিষয়কেstatic
বা থ্রেড স্টোরেজ সময়কালকে বোঝায় যা অন্য কোনও লক-মুক্ত পারমাণবিক বস্তু নয় is হিসাবে ঘোষিত কোনও বস্তুর মান নির্ধারণের চেয়েvolatile sig_atomic_t
...
(void)_;
... এর উদ্দেশ্য কী? এটি কি তাই যে সংকলকটি অব্যবহৃত পরিবর্তনশীল সম্পর্কে সতর্ক করে না?
বিদ্যমান উত্তর সম্পর্কে, নোট করুন যে সিগন্যাল হ্যান্ডলিং প্ল্যাটফর্ম নির্ভর। উদাহরণস্বরূপ উইন 32 পসিক্স অপারেটিং সিস্টেমের চেয়ে কম সংকেত পরিচালনা করে; এখানে দেখুন । উইন 32-এ সিগন্যালগুলিতে সিগিন্ট ঘোষিত হওয়ার সময়, ডকুমেন্টেশনের নোটটি দেখুন যাতে এটি ব্যাখ্যা করে যে এটি আপনার প্রত্যাশার সাথে কাজ করবে না।
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
void sig_handler(int signo)
{
if (signo == SIGINT)
printf("received SIGINT\n");
}
int main(void)
{
if (signal(SIGINT, sig_handler) == SIG_ERR)
printf("\ncan't catch SIGINT\n");
// A long long wait so that we can easily issue a signal to this process
while(1)
sleep(1);
return 0;
}
সিগ_হ্যান্ডলার ফাংশনটি পরীক্ষা করে যদি পাস করা আর্গুমেন্টের মান SIGINT এর সমান হয়, তবে মুদ্রণটি কার্যকর হবে।
প্রস্থান করার আগে এটি কেবল মুদ্রণ করুন।
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void sigint_handler(int);
int main(void)
{
signal(SIGINT, sigint_handler);
while (1){
pause();
}
return 0;
}
void sigint_handler(int sig)
{
/*do something*/
printf("killing process %d\n",getpid());
exit(0);
}