Unix / Linux - Tín hiệu và Bẫy

Trong chương này, chúng ta sẽ thảo luận chi tiết về Tín hiệu và Bẫy trong Unix.

Tín hiệu là các ngắt phần mềm được gửi đến một chương trình để chỉ ra rằng một sự kiện quan trọng đã xảy ra. Các sự kiện có thể thay đổi từ yêu cầu của người dùng đến lỗi truy cập bộ nhớ bất hợp pháp. Một số tín hiệu, chẳng hạn như tín hiệu ngắt, chỉ ra rằng người dùng đã yêu cầu chương trình làm điều gì đó không nằm trong quy trình kiểm soát thông thường.

Bảng sau liệt kê các tín hiệu phổ biến mà bạn có thể gặp phải và muốn sử dụng trong các chương trình của mình -

Tên tín hiệu Số tín hiệu Sự miêu tả
ĐĂNG KÍ 1 Phát hiện treo máy trên thiết bị đầu cuối kiểm soát hoặc chết quá trình kiểm soát
SIGINT 2 Được cấp nếu người dùng gửi tín hiệu ngắt (Ctrl + C)
SIGQUIT 3 Được cấp nếu người dùng gửi tín hiệu thoát (Ctrl + D)
SIGFPE số 8 Được cấp nếu một phép toán bất hợp pháp được cố gắng
SIGKILL 9 Nếu một quá trình nhận được tín hiệu này, nó phải thoát ngay lập tức và sẽ không thực hiện bất kỳ hoạt động dọn dẹp nào
SIGALRM 14 Tín hiệu đồng hồ báo thức (được sử dụng cho bộ hẹn giờ)
SIGTERM 15 Tín hiệu kết thúc phần mềm (được gửi theo mặc định)

Danh sách các tín hiệu

Có một cách dễ dàng để liệt kê tất cả các tín hiệu được hỗ trợ bởi hệ thống của bạn. Chỉ cần phát hànhkill -l lệnh và nó sẽ hiển thị tất cả các tín hiệu được hỗ trợ -

$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
 5) SIGTRAP      6) SIGABRT      7) SIGBUS       8) SIGFPE
 9) SIGKILL     10) SIGUSR1     11) SIGSEGV     12) SIGUSR2
13) SIGPIPE     14) SIGALRM     15) SIGTERM     16) SIGSTKFLT
17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU
25) SIGXFSZ     26) SIGVTALRM   27) SIGPROF     28) SIGWINCH
29) SIGIO       30) SIGPWR      31) SIGSYS      34) SIGRTMIN
35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3  38) SIGRTMIN+4
39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12
47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14
51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7  58) SIGRTMAX-6
59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

Danh sách tín hiệu thực tế khác nhau giữa Solaris, HP-UX và Linux.

Hành động mặc định

Mỗi tín hiệu có một hành động mặc định được liên kết với nó. Hành động mặc định cho một tín hiệu là hành động mà một tập lệnh hoặc chương trình thực hiện khi nó nhận được một tín hiệu.

Một số hành động mặc định có thể xảy ra là:

  • Chấm dứt quá trình.

  • Bỏ qua tín hiệu.

  • Bán phá giá lõi. Điều này tạo ra một tệp có têncore chứa hình ảnh bộ nhớ của tiến trình khi nó nhận được tín hiệu.

  • Dừng quá trình.

  • Tiếp tục một quá trình đã dừng.

Gửi tín hiệu

Có một số phương pháp truyền tín hiệu đến một chương trình hoặc tập lệnh. Một trong những cách phổ biến nhất là người dùng nhậpCONTROL-C hoặc là INTERRUPT key trong khi một tập lệnh đang thực thi.

Khi bạn nhấn Ctrl+C chìa khóa, một SIGINT được gửi đến tập lệnh và theo như đã định nghĩa thì tập lệnh hành động mặc định sẽ kết thúc.

Phương pháp phổ biến khác để phân phối tín hiệu là sử dụng kill command, cú pháp của nó như sau:

$ kill -signal pid

Đây signal là số hoặc tên của tín hiệu cần phân phối và pidlà ID quá trình mà tín hiệu sẽ được gửi đến. Ví dụ -

$ kill -1 1001

Lệnh trên sẽ gửi tín hiệu HUP hoặc tín hiệu treo máy đến chương trình đang chạy với process ID 1001. Để gửi tín hiệu kết thúc cho cùng một quá trình, hãy sử dụng lệnh sau:

$ kill -9 1001

Điều này giết chết quá trình đang chạy với process ID 1001.

Tín hiệu bẫy

Khi bạn nhấn tổ hợp phím Ctrl + C hoặc phím Break tại thiết bị đầu cuối trong khi thực thi chương trình shell, thông thường chương trình đó sẽ bị kết thúc ngay lập tức và dấu nhắc lệnh của bạn sẽ trở lại. Điều này có thể không phải lúc nào cũng mong muốn. Ví dụ: bạn có thể để lại một loạt các tệp tạm thời không được dọn dẹp.

Bẫy các tín hiệu này khá dễ dàng và lệnh bẫy có cú pháp sau:

$ trap commands signals

Lệnh here có thể là bất kỳ lệnh Unix hợp lệ nào hoặc thậm chí là một hàm do người dùng xác định và signal có thể là danh sách bất kỳ số lượng tín hiệu nào bạn muốn bẫy.

Có hai cách sử dụng phổ biến cho bẫy trong tập lệnh shell:

  • Dọn dẹp các tệp tạm thời
  • Bỏ qua tín hiệu

Xóa các tệp tạm thời

Là một ví dụ về lệnh bẫy, phần sau cho thấy cách bạn có thể xóa một số tệp và sau đó thoát nếu ai đó cố gắng hủy bỏ chương trình khỏi thiết bị đầu cuối:

$ trap "rm -f $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 2

Từ điểm trong chương trình shell mà bẫy này được thực thi, hai tệp work1$$dataout$$ sẽ tự động bị loại bỏ nếu chương trình nhận được tín hiệu số 2.

Do đó, nếu người dùng làm gián đoạn việc thực thi chương trình sau khi bẫy này được thực hiện, bạn có thể yên tâm rằng hai tệp này sẽ được dọn sạch. Cácexit lệnh theo sau rm là cần thiết vì nếu không có nó, quá trình thực thi sẽ tiếp tục trong chương trình tại điểm mà nó đã dừng lại khi nhận được tín hiệu.

Tín hiệu số 1 được tạo ra cho hangup. Có thể ai đó cố tình ngắt đường dây hoặc đường dây vô tình bị ngắt kết nối.

Bạn có thể sửa đổi bẫy trước để loại bỏ hai tệp được chỉ định trong trường hợp này bằng cách thêm tín hiệu số 1 vào danh sách tín hiệu -

$ trap "rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 1 2

Bây giờ các tệp này sẽ bị xóa nếu dòng bị treo hoặc nếu phím Ctrl + C được nhấn.

Các lệnh được chỉ định để bẫy phải được đặt trong dấu ngoặc kép, nếu chúng chứa nhiều hơn một lệnh. Cũng lưu ý rằng trình bao quét dòng lệnh tại thời điểm lệnh bẫy được thực thi và cả khi nhận được một trong các tín hiệu được liệt kê.

Do đó, trong ví dụ trước, giá trị của WORKDIR$$sẽ được thay thế tại thời điểm lệnh bẫy được thực hiện. Nếu bạn muốn sự thay thế này xảy ra tại thời điểm nhận được tín hiệu 1 hoặc 2, bạn có thể đặt các lệnh bên trong dấu nháy đơn -

$ trap 'rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit' 1 2

Bỏ qua tín hiệu

Nếu lệnh được liệt kê cho bẫy là rỗng, tín hiệu được chỉ định sẽ bị bỏ qua khi nhận được. Ví dụ, lệnh -

$ trap '' 2

Điều này chỉ định rằng tín hiệu ngắt sẽ được bỏ qua. Bạn có thể muốn bỏ qua một số tín hiệu khi thực hiện một thao tác mà bạn không muốn bị gián đoạn. Bạn có thể chỉ định nhiều tín hiệu bị bỏ qua như sau:

$ trap '' 1 2 3 15

Lưu ý rằng đối số đầu tiên phải được chỉ định cho một tín hiệu bị bỏ qua và không tương đương với việc viết lệnh sau, đối số này có ý nghĩa riêng của nó -

$ trap  2

Nếu bạn bỏ qua một tín hiệu, tất cả các trang con cũng bỏ qua tín hiệu đó. Tuy nhiên, nếu bạn chỉ định một hành động được thực hiện khi nhận được tín hiệu, tất cả các biểu mẫu con sẽ vẫn thực hiện hành động mặc định khi nhận được tín hiệu đó.

Đặt lại bẫy

Sau khi bạn đã thay đổi hành động mặc định được thực hiện khi nhận được tín hiệu, bạn có thể thay đổi lại hành động đó với bẫy nếu bạn chỉ bỏ qua đối số đầu tiên; vì vậy -

$ trap 1 2

Điều này đặt lại hành động được thực hiện khi nhận tín hiệu 1 hoặc 2 trở lại mặc định.