Signal Programming

การส่งสัญญาณ (signal) ถือว่าเป็นการส่งข้อมูลขั้นพื้นฐานระหว่างโปรเซสภายใต้ระบบปฏิบัติการลีนุกซ์ โดยโปรเซสหนึ่งจะส่งสัญญาณไปยังอีกโปรเซสหนึ่ง เมื่ออีกโปรเซสที่ได้รับสัญญาณที่ถูกแทรกเข้ามา (interrupt) มันก็จะดำเนินการคำสั่งที่ถูกตั้งเอาไว้ทันที ซึ่งเมื่อเริ่มแรกของการนำสัญญาณมาใช้นั้น จะเป็นเพียงรูปแบบสัญญาณที่ไม่ได้แยกแยะชนิดหรือประเภทของสัญญาณอะไรมากมายแต่ในปัจจุบันการพัฒนาของระบบปฏิบัติการลีนุกซ์มีความซับซ้อนมากขึ้น รวมทั้งการสื่อสารระหว่างโปรเซสก็ต้องการเงื่อนไขที่หลากหลายมากขึ้นเช่นกัน จึงทำให้มีการกำหนดประเภทของสัญญาณ (signal type) ขึ้นมาโดยมีชนิดเป็นเลขจำนวนเต็ม (integer value) ตัวอย่างเช่น เลข 15 (SIGTERM) แทนสัญญาณสิ้นสุดการทำงาน (Terminate) ซึ่งหมายเลขสัญญาณต่างๆจะถูกกำหนดอยู่ในฟังก์ชัน signal.h

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) SIGCONT

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

ตัวอย่างการส่งสัญญาณผ่านคีย์บอร์ด

Ctrl-C

ส่งสัญญาณ INT (SIGINT) ไปยังโปรเซสที่ทำงานอยู่ยุติการทำงานทันที

Ctrl-Z

ส่งสัญญาณ TSTP (SIGTSTP) ไปยังโปรเซสที่ทำงานอยู่ให้หยุดชั่วคราว

Ctrl-\

ส่งสัญญาณ ABRT (SIGABRT) ไปยังโปรเซสที่ทำงานอยู่ให้ยุติการทำงานของโปรเซสนั้นทันที เหมือน Ctrl-C แต่เป็นคำสั่งที่ดีกว่าคือสามารถแก้ไขได้

นอกจากนั้นจะมีการเรียกใช้ฟังก์ชัน kill() เพื่อทำการส่งสัญญาณออกไปยังโปรเซสปลายทาง โดยที่โปรเซสรับปลายทางจะมีการกำหนดไว้ว่าถ้าได้รับสัญญาณหมายเลขนี้ ก็ให้ดำเนินการเรียกฟังก์ชันที่กำหนดไว้ต่อไป ด้วยการเรียกใช้ฟังก์ชัน signal() อย่างไรก็ตามโปรเซสต่างๆที่อยู่ภายใต้ผู้ใช้คนเดียวกัน จะสามารถส่งสัญญาณถึงกันได้ แต่ไม่สามารถส่งสัญญาณไปยังโปรเซสอื่นๆของผู้ใช้คนอื่นได้ ยกเว้นโปรเซสของ superuser เท่านั้น

ฟังก์ชันและตัวแปรที่เกี่ยวข้อง

  • ฟังก์ชัน void signal(int sig_type, void (*sig_handler)(int signal_type))

    • sig_type แทนค่าของสัญญาณที่จะตรวจจับ (ดูจากไฟล์ signal.h)

      • sig_handles แทนค่าตัวชี้ (pointer) ไปยังฟังก์ชันที่สร้างขึ้นมาเพื่อดำเนินการเมื่อได้รับสัญญาณที่ตรวจจับได้

  • ฟังก์ชัน int kill (pid_t dest_pid, int sig_type)

    • เป็นฟังก์ชันที่ใช้ในการส่งสัญญาณที่ต้องการ (sig_type) ไปยังโปรเซสปลายทาง (dest_pid) นอกจากนั้นถ้ามีการกำหนดค่า dest_pid เป็น 0 จะหมายถึงการส่งไปยังทุกโปรเซสของผู้ใช้เดียวกัน แต่ถ้ากำหนดค่า dest_pid เป็น -1 เมื่อใดจะหมายถึงการส่งไปยังทุกโปรเซสในระบบ (แต่ใช้ได้เฉพาะเป็น superuser เท่านั้น)

  • ฟังก์ชัน void raise (int sig_type)

    • ใช้ในกรณีที่ต้องการส่งสัญญาณ (sig_type) ให้ตัวเอง

สิ่งที่ควรรู้

  • โปรเซสจะได้รับสัญญาณได้ทั้งผ่านโปรเซสในกลุ่มเดียวกันของผู้ใช้นั้นส่งมาหรือผู้ใช้ในระดับ superuser เป็นผู้ส่งมาให้เอง

  • ชนิดของสัญญาณและชื่อของสัญญาณถูกกำหนดอยู่ในไฟล์ signal.h

  • สัญญาณที่ถูกส่งไปจะไม่สามารถถูกเก็บเข้าคิวได้

  • ตัวจัดการที่ใช้ในการสิ้นสุดโปรเซสคือ SIG_DFL และ SIG_IGN ในกรณีต้องการเพิกเฉยต่อสัญญาณที่เข้ามา ตัวอย่างเช่นsignal (SIGINT, SIG_IGN);

ตัวอย่างที่ 1

แสดงตัวอย่างการกำหนดฟังก์ชันที่จะให้ดำเนินการเมื่อตรวจจับสัญญาณที่กำหนดไว้ ซึ่งในตัวอย่างนี้จะตรวจสอบสัญญาณหมายเลข 2 (SIGINT)

กลไกการทำงานของ signalling

ตัวอย่างที่ 2

แสดงตัวอย่างโปรเซสลูกจะวนรอรับ signal ที่จะถูกส่งมาจากผู้ใช้เช่น Ctrl+C เป็นต้น โดยโปรเซสแม่จะรอโปรเซสลูกจนกว่าจะทำงานสิ้นสุด

ตัวอย่างที่ 3

แสดงตัวอย่างการใช้ฟังก์ชัน alarm(5) เพื่อสร้างสัญญาณขึ้นทุกๆ 5 วินาที

จากผลการทำงานของโปรแกรมข้างต้นเมื่อมีการทำงานของคำสั่ง alarm(5) ที่มีการสร้างสัญญาณขึ้นทุกๆ 5 วินาที แล้วทำให้มีการเรียกฟังก์ชัน HL_AlarmSig() เพื่อแสดงข้อความนับเวลา แล้วเพิ่มค่าตัวแปร count ขึ้นไปเรื่อยๆ จนกระทั่งเมื่อค่าในตัวแปร count เพิ่มขึ้นจนเท่ากับหรือมากกว่า 12 โปรเซสแม่ก็จะสิ้นสุดการทำงานของตัวเอง ดังนั้นเมื่อรวมเวลาที่นับแล้วเท่ากับ 60 วินาที (12 x 5) นั่นเอง

ตัวอย่างที่ 4

แสดงตัวอย่างโปรแกรมตรวจสอบสัญญาณตามที่กำหนดเพื่อเรียกไปยังฟังก์ชันที่กำหนดไว้

ตัวอย่างที่ 5

แสดงตัวอย่างโปรแกรม

ตัวอย่างที่ 6

แสดงตัวอย่างโปรแกรมที่ใช้สำหรับแก้ปัญหาการจัดการคิวของการสิ้นสุดของโปรเซสลูกที่แตกต่างกรณีกัน (exit statues) ซึ่งเมื่อไหร่ก็ตามที่สถานะของโปรเซสลูกเปลี่ยนแปลงโปรเซสแม่ก็จะได้รับสัญญาณ SIGCHLD

Last updated

Was this helpful?