pthreads(7)
mô tả rằng POSIX.1 yêu cầu tất cả chủ đề trong một quá trình cổ phần thuộc tính, bao gồm:
POSIX.1 cũng đòi hỏi một số thuộc tính được biệt cho mỗi thread , bao gồm:
Linux kernel đã khối mã sau - những ý kiến khá hữu ích:
/*
* Now find a thread we can wake up to take the signal off the queue.
*
* If the main thread wants the signal, it gets first crack.
* Probably the least surprising to the average bear.
*/
if (wants_signal(sig, p))
t = p;
else if (!group || thread_group_empty(p))
/*
* There is just one thread and it does not need to be woken.
* It will dequeue unblocked signals before it runs again.
*/
return;
else {
/*
* Otherwise try to find a suitable thread.
*/
t = signal->curr_target;
while (!wants_signal(sig, t)) {
t = next_thread(t);
if (t == signal->curr_target)
/*
* No thread needs to be woken.
* Any eligible threads will see
* the signal in the queue soon.
*/
return;
}
signal->curr_target = t;
}
/*
* Found a killable thread. If the signal will be fatal,
* then start taking the whole group down immediately.
*/
if (sig_fatal(p, sig) &&
!(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) &&
!sigismember(&t->real_blocked, sig) &&
(sig == SIGKILL || !t->ptrace)) {
/*
* This signal will be fatal to the whole group.
*/
Vì vậy, bạn thấy rằng bạn chịu trách nhiệm về nơi tín hiệu được phân phối:
Nếu quy trình đã đặt bố cục của tín hiệu thành SIG_IGN
hoặc SIG_DFL
, sau đó tín hiệu bị bỏ qua (hoặc mặc định - giết, lõi hoặc bỏ qua) cho tất cả các chuỗi.
Nếu quy trình của bạn đã đặt bố cục tín hiệu thành một trình xử lý cụ thể, bạn có thể kiểm soát luồng nào sẽ nhận tín hiệu bằng cách thao tác các mặt nạ tín hiệu chủ đề cụ thể bằng cách sử dụng pthread_sigmask(3)
. Bạn có thể chỉ định một luồng để quản lý tất cả hoặc tạo một chuỗi cho mỗi tín hiệu hoặc bất kỳ hỗn hợp nào của các tùy chọn này cho các tín hiệu cụ thể hoặc bạn dựa vào hành vi mặc định hiện tại của hạt nhân Linux để phân phối tín hiệu cho chuỗi chính.
Một số tín hiệu, tuy nhiên, là đặc biệt:
A signal may be generated (and thus pending) for a process as
a whole (e.g., when sent using kill(2)) or for a specific
thread (e.g., certain signals, such as SIGSEGV and SIGFPE,
generated as a consequence of executing a specific machine-
language instruction are thread directed, as are signals
targeted at a specific thread using pthread_kill(3)). A
process-directed signal may be delivered to any one of the
threads that does not currently have the signal blocked. If
more than one of the threads has the signal unblocked, then
the kernel chooses an arbitrary thread to which to deliver
the signal.
Và những gì xảy ra bên trong sợi rễ khi một tín hiệu nhận được? Hãy nói rằng tôi đã viết một xử lý tín hiệu tùy chỉnh cho SIGUSR1, và bây giờ tôi đang gửi tín hiệu đó cho quá trình. Chủ đề gốc sẽ nhận được tín hiệu đó. Có lẽ nó đang ở giữa một số chức năng tại thời điểm đó. Chuyện gì đang xảy ra vậy? –
nếu bạn có thiết lập trình xử lý, nó sẽ được coi là gián đoạn và luồng chương trình sẽ tạm dừng và trình xử lý tùy chỉnh của bạn sẽ được thực thi. Một khi nó được thực hiện, điều khiển sẽ trở lại, giả sử bạn đã không làm bất cứ điều gì để thay đổi dòng chảy bình thường (thoát ra vv). – Alan
Lưu ý rằng điều này là dành riêng cho SIGUSR1, mà IIRC không làm gián đoạn các cuộc gọi hệ thống. Nếu bạn đã thử điều này với SIGINT chẳng hạn, nó có thể làm gián đoạn luồng đọc và khi bạn quay lại đọc, luồng có thể trả lại lỗi bị gián đoạn. – Alan