시그널 핸들러에 인자 제공 / 전달
신호 처리기에 인수를 제공 / 전달할 수 있습니까?
/* Signal handling */
struct sigaction act;
act.sa_handler = signal_handler;
/* some more settings */
이제 핸들러는 다음과 같습니다.
void signal_handler(int signo) {
/* some code */
}
임시 파일 삭제와 같이 특별한 작업을 수행하려면 해당 파일을이 핸들러에 대한 인수로 제공 할 수 있습니까?
편집 0 : 답변 주셔서 감사합니다. 일반적으로 전역 변수 사용을 피하거나 권장하지 않습니다. 이 경우 거대한 프로그램이 있으면 다른 곳에서 일이 잘못 될 수 있으며 많은 정리 작업이 필요할 수 있습니다. API가 이렇게 설계된 이유는 무엇입니까?
매개 변수로 신호 처리기에 자신의 데이터를 전달할 수 없습니다. 대신 매개 변수를 전역 변수에 저장해야합니다. ( 시그널 핸들러를 설치 한 후 데이터 를 변경 해야하는 경우에는 정말 조심해야합니다 .)
편집에 대한 응답 0 : 역사적 이유. 신호는 정말 오래되고 정말 낮은 수준의 디자인입니다. 기본적으로 커널에 일부 기계 코드에 대한 단일 주소가 주어지고 그러한 경우 특정 주소로 이동하도록 요청합니다. 우리는 여기에서 "휴대용 어셈블러"사고 방식으로 돌아 왔습니다. 여기서 커널은 노 프릴 기본 서비스를 제공하고 사용자 프로세스가 합리적으로 예상 할 수있는 모든 것이 자체적으로 수행되어야합니다.
또한 전역 변수에 대한 일반적인 인수는 여기에 실제로 적용되지 않습니다. 신호 처리기 자체 는 전역 설정이므로 주변에 사용자 지정 매개 변수 집합이 여러 개있을 가능성이 없습니다. (글쎄요, 실제로는 전적으로 전역 적이 지 않고 스레드 전역일뿐입니다. 그러나 스레딩 API에는이 경우에 필요한 스레드 로컬 저장소에 대한 일부 메커니즘이 포함됩니다.)
신호 처리기 등록은 이미 전역 변수에 해당 하는 전역 상태 입니다. 따라서 인수를 전달하기 위해 전역 변수를 사용하는 것은 더 이상 불쾌하지 않습니다. 그러나 어쨌든 시그널 핸들러에서 무엇이든 하는 것은 큰 실수입니다 ( 전문가가 아니면 거의 정의되지 않은 행동입니다 !). 대신 신호를 차단하고 기본 프로그램 루프에서 신호를 폴링하면 이러한 모든 문제를 피할 수 있습니다.
이것은 정말 오래된 질문이지만 귀하의 문제에 대한 답을 얻을 수있는 멋진 트릭을 보여 드릴 수 있다고 생각합니다. sigqueue 등을 사용할 필요가 없습니다.
또한 전역 변수의 사용이 싫기 때문에 제 경우에는 void ptr (나중에 필요에 맞게 캐스팅 할 수 있음)을 보내는 영리한 방법을 찾아야했습니다.
실제로 할 수 있습니다.
signal(SIGWHATEVER, (void (*)(int))sighandler); // Yes it works ! Even with -Wall -Wextra -Werror using gcc
그러면 sighandler는 다음과 같습니다.
int sighandler(const int signal, void *ptr) // Actually void can be replaced with anything you want , MAGIC !
다음과 같이 질문 할 수 있습니다. * ptr을 얻는 방법?
방법은 다음과 같습니다 . 초기화시
signal(SIGWHATEVER, (void (*)(int))sighandler)
sighandler(FAKE_SIGNAL, your_ptr);
sighandler func에서 :
int sighandler(const int signal, void *ptr)
{
static my_struct saved = NULL;
if (saved == NULL)
saved = ptr;
if (signal == SIGNALWHATEVER)
// DO YOUR STUFF OR FREE YOUR PTR
return (0);
}
물론. 일반적인 kill () 대신 sigqueue ()를 사용하여 정수와 포인터를 신호 처리기에 전달할 수 있습니다.
http://man7.org/linux/man-pages/man2/sigqueue.2.html
전역 변수에 파일 이름을 저장 한 다음 핸들러에서 액세스합니다. 신호 처리기 콜백은 문제를 일으킨 실제 신호의 ID (예 : SIGINT, SIGTSTP) 하나만 전달됩니다.
Edit 0: "There must be a rock solid reason for not allowing arguments to the handler." <-- There is an interrupt vector (basically, a set of jump addresses to routines for each possible signal). Given the way that the interrupt is triggered, based on the interrupt vector, a particular function is called. Unfortunately, it's not clear where the memory associated with the variable will be called, and depending on the interrupt that memory may actually be corrupted. There is a way to get around it, but then you can't leverage the existing int 0x80 assembly instruction (which some systems still use)
You can use a signal handler which is a method of a class. Then that handler can access member data from that class. I'm not entirely sure what Python does under the covers here around the C signal() call, but it must be re-scoping data?
I was amazed that this works, but it does. Run this and then kill the process from another terminal.
import os, signal, time
class someclass:
def __init__(self):
self.myvalue = "something initialized not globally defined"
signal.signal(signal.SIGTERM, self.myHandler)
def myHandler(self, s, f):
# WTF u can do this?
print "HEY I CAUGHT IT, AND CHECK THIS OUT", self.myvalue
print "Making an object"
a = someclass()
while 1:
print "sleeping. Kill me now."
time.sleep(60)
ReferenceURL : https://stackoverflow.com/questions/6970224/providing-passing-argument-to-signal-handler
'developer tip' 카테고리의 다른 글
작업 복사본을 수정하지 않고 Git 브랜치를 리베이스 할 수 있습니까? (0) | 2021.01.08 |
---|---|
파이썬 : 함수에 대한 정보를 얻는 방법? (0) | 2021.01.08 |
CoffeeScript는 JavaScript 스타일 == 같음 의미를 허용합니까? (0) | 2021.01.08 |
Objective-C 자동 참조 계산과 가비지 수집의 차이점은 무엇입니까? (0) | 2021.01.08 |
내부 (0) | 2021.01.08 |