Showing posts with label kill. Show all posts
Showing posts with label kill. Show all posts

Friday, October 26, 2012

UNIX Programming

signal

ในตอนนี้เราจะพูดถึงการรับมือกับ signal ไม่ว่าจะมาจากภายนอก เช่น interrupt หรือจากในภายในโปรแกรมเอง และเนื่องจากว่า ในภายในตัวโปรแกรมเองนั้น ไม่มีอะไรน่าสนใจมากไปกว่า การอ้างถึงหน่วยความจำ ที่อ้างไม่ถึง หรือ อยู่นอกขอบข่ายที่จะอ้างอิงถึงได้ กับ การใช้คำสั่งที่แปลกประหลาด เราจึงมุ่งความสนใจไปที่ signal จากภายนอก เช่น

  • interrupt เมื่อมีการกดปุ่ม Delete
  • quit เมื่อกดปุ่ม FS
  • hangup เมื่อเกิดการวางสายโทรศัพท์ลง
  • terminate เมื่อได้รับคำสั่ง kill
เมื่อเกิด เหตุการ, event, เหล่านี้ขึ้น signal จะได้รับการส่ง หรือ ประกาศไปยังทุก process ที่ทำงานบน terminal นั้นๆ ซึ่งหากไม่มีการตระเตรียมอื่นใดเป็นพิเศษแล้ว signal มักจะหยุดการทำงานของ process และในกรณีของ quit จะได้แฟ้มเสมือน ในหน่วยความจำ ในขณะนั้นมาให้ เพื่อตรวจสอบดู หรือ debug ในภายหลัง
routine ที่เปลี่ยนแปลงการกระทำโดยปริยายเมื่อได้รับ signal ก็คือ signal() ซึ่งใช้ชื่อเดียวกันเอง รูทีนนี้ หรือ function นี้ต้องการอาร์กิวเม้นต์ ๒ ตัว คือ
  • ตัว signal
  • บอกว่าจะทำอะไร อย่างไรกับ signal นี้
ค่าแรกนั้น เป็นเพียงตัวเลขที่นิยามเอาไว้เท่านั้นเอง ไม่ได้มีความหมายอะไรมากนัก แต่ค่าที่สองนั้น เป็น address ซึ่งชี้ไปที่ function หรือ คำสั่งประหลาดยากแก่การเข้าใจ แต่โดยทั่วไป ก็ว่า ให้ละความสนใจ signal นี้ หรือ ให้ปฏิบัติตามข้อตกลงโดยปริยายของ signal นี้ที่กำหนดเอาไว้แล้ว อย่างไรก็ดี แฟ้ม signal.h ต้องระบุเอาไว้ด้วย เพื่อการเรียกใช้งาน signal ต่างๆ

#include <signal.h>

signal(SIGINT, SIG_IGN);

คำสั่งข้างบนนั้นเป็นเหตุให้ การ interrupt นั้นได้รับการละเลยไปเสีย กล่าวคือ ไม่ต้องไปสนใจอะไร นั่นเอง ขณะที่

signal(SIGINT, SIG_DFL);

นั้น จะนำการปฏิบัติการ ตามค่าปริยายกลับคืนมา ซึ่งก็คือ จบงาน

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

#include <signal.h>

main()
{
     int onintr();

     if (signal(SIGINT, SIG_IGN) != SIG_IGN);
         signal(SIGINT, onintr);

/* process ...
 */
      exit(0);
}

onintr()
{
     unlink(tempfile);
     exit(1);
}

ความวุ่นวาย มันก็อยู่ที่ประโยค if () นั่นแหละ ตรงที่ต้องเรียก signal() สองหน

เรื่องก็มีอยู่ว่า ในกรณีของ interrupt นั้น signal จะส่งไปยังทุก process ที่ทำงานบน terminal นั้นๆ ที่นี้ ขอให้ดูบางโปรเซส ที่เขาทำงาน  โดยไม่ต้องการการรบกวนใดใด จากแป้นพิมพ์เลย งานแบบนี้ จะหยุดก็เมื่องานเสร็จ หรือเกิดอุบัติเหตุบางอย่างเท่านั้น ดังนั้น จึงสามารถสั่งงานประเภทนี้ ให้วิ่งในลักษณะของ background ได้ ก็คำสั่ง จาก shell ที่มีตัว & ปิดท้ายนั่นเอง , ให้สังเกตุตัวคำสั่งด้วย
signal(SIGINT, SIG_IGN)
ซึ่งระบุเอาไว้ว่า ถ้ามี interrupt เข้ามาก็ไม่ต้องไปสนใจน่ะ

ทีนี้ ถ้าหากว่า ตัวอย่างโปรแกรมข้างบนนั้น ทำงานเลย โดยไม่ต้องไปตรวจดูว่า signal เดิม ที่ตั้งเอาไว้นั้น คืออะไร ก็ไยมิใช่เท่ากับว่า ความพยายามที่จะทำงานให้เสร็จ นั้น ล้มเหลว จริงไหมครับ

ดังนั้น เราจึงดูว่าค่า signal ของ signal() ที่กำหนดไว้เดิมนั้น ใช่ ignore (SIG_IGN) หรือไม่ แล้วค่านี้จะได้มาก็โดยการเรียกด้วย signal() เท่านั้น นี่คือนัยยะของบรรทัด if() นั้น

บรรทัดถัดมานั่นจึงเป็นการส่ง signal ที่แท้จริง กล่าวคือ ให้ไปทำงานใน function onintr() น่ะ หากมีสัญญาน interrupt มาแล้ว ก็เท่านี้แหละ

นอกจากนี้แล้ว นิยาม หรือค่าที่กำหนดใน SIG_DLF, SIG_IGN เองก็ น่าเกลียด น่ากลัวเอามากมากพอ จนไม่อยากให้เรียกตรงๆ แต่กำหนดผ่าน #define เอา ก็ลองดูซิว่า จะเข้าใจหรือเปล่า

#define     SIG_DFL  (int (*)())0
#define     SIG_IGN  (int (*)())1

ยังมีสาระที่ขออนุญาตข้ามไปก่อน โดยเฉพาะในเรื่องของการ fork() นั้น จะไม่ขออธิบายละ แต่ยกเอา code สั้นๆมาให้ดูชมกัน แล้วพิจารณาเอาเองว่า ทำไม และขอยุติลงไว้แต่เพียงเท่านี้

if (fork() == 0)
      execl( .. );
signal(SIGINT, SIG_IGN);
wait(&status);
signal(SIGINT, onintr);

Tuesday, August 17, 2010

syslog: The system events logger

commands
ต่อจาก ตอนก่อนหน้านี้น่ะ ยกยอดมาเลย ดูดีกว่า

syslog เป็นโปรแกรมที่จัดการข้อมูลทั้งจาก kernel และ โปรแกรมอรรถประโยชน์ของระบบ เขียนโดย Eric Allman จาก Berkeley โปรแกรมนี้ มีข้อดีที่สำคัญ ๒ ประการคือ
  1. ทำให้ผู้พัฒนาโปรแกรม เป็นอิสระจากความจำเป็นที่ต้องมีการบันทึก log และ
  2. เอื้ออำนวยให้ ผู้บริหารระบบสามารถควบคุมการเก็บ log ได้
ก่อนหน้านี้ ต่างคน ต่างมีอิสระในการบันทึก log ของตัวของตัวไป ผู้บริหารระบบ ไม่สามารถควบคุมได้ว่าข้อมูลอันใดที่จะเก็บไว้ หรือ สมควรเก็บไว้ และ จะเก็บไว้ที่ไหน

syslog มีความหยืดหยุ่นพอสมควร กล่าวคือสามารถเรียงลำดับข่าวสารจากแหล่งกำเนิด และ ความสำคัญ(รวมๆเรียกแบบเหมาโหลว่า severity [security ขออภัย คำนี้ คัดลอกมาผิดครับ ที่ถูกคือ ซิเวียริตี้] level) ได้ และเปิดช่องทางของข่าวสารอันนั้น ไปยังจุดหมายปลายทางใดใดได้ เช่นลง log หรือ บน terminal ของผู้ใช้งานเอง หรือ เครื่องอื่นๆ ก้ยังได้

ความสามารถในการที่จะเป็นศูนย์กลางการ log ข่าวสารของเครือข่ายนี้เอง เป็นคุณสมบัติเด่นอันหนึ่งของเขา

syslog ประกอบด้วยสามองค์ใหญ่ๆคือ
  1. syslogd และ /etc/syslog.conf ตัวโปรแกรมที่ดำเนินการบันทึก และ แฟ้มที่บ่งบอกพฤติกรรมของเขา
  2. openlog, syslog,closelog รูทีนสำคัญๆที่อยู่ใน library ที่ผู้พัฒนาโปรแกรมใช้สำหรับส่งข้อมูลไปให้กับ syslogd และ
  3. logger คำสั่งในระดับผู้ใช้งาน ที่สามารถเรียกใช้เพื่อส่ง log ต่างๆ

syslogd อยู่ที่ /usr/sbin ส่วน logger อยุ่ที่ /usr/bin และ syslog เป็นรูทีนใน library ที่เป็นส่วนหนึ่งของ C standard library.

การทำงาน จะเป็นลักษณะนี้ โดยที่แรกเริ่ม syslogd จะวิ่งเมื่อเปิดระบบปฏิบัติการ โปรแกรมที่ทำงานร่วมกับ syslog จะเขียน log ลงไปยังแฟ้มพิเศษ ชื่อ /dev/log ส่วน syslogd จะอ่านข่าวสารจากแฟ้มนี้ ปรึกษาแฟ้มที่กำหนดพฤติกรรมของเขา แล้วแยกกระจายไปยังปลายทางต่างๆ ตามที่กำหนดไว้. syslogd จะอ่านข่าวสารต่างๆจาก kernel ด้วยเช่นกัน โดยอ่านจากอุปกรณ์ /dev/klog

สัญญาณควบคุม HUP จะทำให้ syslogd ปิดแฟ้ม log อ่านแฟ้มที่ควบคุมพฤติกรรมของเขาใหม่อีกครั้งหนึ่ง และ เริ่มต้นการบันทึกอีกระลอกใหม่ นั่นก็หมายความว่า หากมีการเปลี่ยนแปลงใดใดกับแฟ้มควบคุมพฤติกรรมของ syslogd แล้ว ท่านต้อง ส่งสัญญาณ HUP ให้กับ syslogd เพื่อว่า การเปลี่ยนแปลงนั้นๆ จะมีผลบังคับใช้ สัญญาณควบคุม TERM จะเป็นการสั่งยุติการทำงานของ syslogd

syslogd เขาจัเขียน process ID, PID, ไว้ที่แฟ้ม /var/run/syslog.pid ดังนั้น จึงสะดวกมาก สำหรับการสั่ง หรือ ส่งสัญญาณ ไปยัง process นั้นๆ ดังนี้ (โปรดใช้ความละเอียดถี่ถ้วนเป็นอย่างยิ่ง)
kill   -1   `/bin/cat /var/run/syslog.pid`
สัญญาณส่งผ่านคำสั่ง kill โดยเป็น option ของคำสั่ง ตามรูปแบบที่นำเสนอนี้ 1 หรือ HUP คือสัญญาณดังกล่าว

การบีบอัด และโยกย้ายแฟ้ม log จาก syslogd โดยพละการนั้น ไม่ดี และผลเสียมากเกินคาดคิดเลยทีเดียว ปกติระบบจะมีโปรแกรมเล็กๆช่วยงานลักษระนี้อยู่แล้ว

ในลำดับถัดไปจะนำเสนอส่วนของการควบคุมพฤติกรรมของ syslogd ซึ่งก็คือรายละเอียดของแฟ้ม /etc/syslog.conf ซึ่งสาระของแฟ้มนี้เขียนขึ้นด้วยอักษรธรรมดาๆ ไม่ต้องการอะไรมาก โดยมีข้อกำหนดว่า บรรทัดว่างๆ กับ บรรทัดที่ขึ้นต้นด้วย # นั้น มันจะไม่สนใจ มันจะสนใจก็ต่อเมื่อ บรรทัดนั้นๆ อยู่ในรูปแบบดังนี้
selector<Tab>action
โดยที่ <Tab> คือปุ่ม Tab บนแป้นพิมพ์ของท่าน และเป็นปุ่ม Tab เพียงเท่านั้น จะเป็นอย่างอื่นไปเสียไม่ได้ สำหรับ selector และ action นั้น จะได้นำมาเล่าต่อไป๚

Tuesday, April 1, 2008

process

การจัดการกับ process

process คือ programme ที่กำลังดำเนินไปในขณะใดขณะหนึ่ง สำหรับขณะนี้ ใคร่ขอเสนอจำเพาะเรื่องง่ายๆ พื้นๆของ process ก่อนคือ ดูสถานะของ process การหยุด process

การดูสถานะของ process
ใน FreeBSD การดูว่าขณะนี้ระบบมี process อะไรกำลังดำเนินไปอยู่สามารถกระทำได้ด้วยคำสั่ง ps(1) โดยกำหนด options ต่างๆดังนี้

# ps -axu

ผลลัพธ์มันจะหลาย column ยังไงก็ช่าง แต่เบื้องต้น ขอให้สนใจจำเพาะ ๒ column แรก และ column ขวาสุด ซึ่งมีหัว column เป็น USER, PID, COMMAND ตามลำดับนั้น
ความจริงแทบจะไม่ต้องบรรยายอะไรมากเลย เพราะก็บอกชัดๆอยู่แล้วว่าหมายถึง ชื่อ ของผู้เป็นเจ้าของ process นั้นๆ ซึ่ง ชื่อ นี้ก็คือ login ID ที่ใช้ในตอน login นั่นเองสำหรับ column แรกสุด
ส่วน column ขวาสุด ก็เห็น และเข้าใจได้เลยว่า process นั้นใช้คำสั่งอะไรวิ่ง
และที่สุด column ที่เหลือ นั้น หมายถึง process identification ที่กำลังวิ่งอยู่ว่ามีหมายเลข process อะไร การเรียกด้วยหมายเลข ทำให้สะดวก และง่ายขึ้น

รายละเอียดที่เหลือ สามารถหาอ่านเอาเองได้จาก man 1 ps ซึ่งก็คือที่เขียนไว้เป็น ps(1) ในตอนต้นนั่นเอง อย่างไรก็ดีก่อนจากในภาคนี้ ขอแนะให้ท่านลองสั่ง

# ps -axuwwwwww

คือให้ต่อท้ายด้วยตัว w ไปให้มากโดยเริ่มที่ ๑ ตัวก่อน แล้วเพิ่มไปทีละตัว แล้วสังเกตุถึงความแตกต่างที่เห็น

การหยุด process
สำหรับการหยุด process นั้น เราอาศัย pid ที่ได้จากภาคที่แล้วมาใช้ประโยชน์ โดยการสั่ง ฆ่า process นั้นๆ คำสั่งที่ใช้คือ kill(1) รูปแบบของคำสั่งทั่วๆไปคือ

# kill PID

เมื่อ PID นั้นคือหมายเลขของ process ที่ได้จาก ps(1) ที่ได้นำเสนอไปแล้ว
บางครั้งเราพบว่าแม้จะสั่ง ฆ่า ไปแล้ว แต่ process นั้นๆยังไม่ตายทันที และบางทีก็นานจนสังเกตุได้ด้วย กว่าจะตาย วิธีแก้ไขคือ ตอนสั่ง ฆ่า ไปนั้น เราต้องบอกด้วยว่า ใช้อาวุธอะไร สำหรับฆ่า เพราะบางที นักฆ่า เขาอาจจะเอาอาวุธพื้นๆไปใช้กับเป้าหมายที่ เส้นใหญ่ ก็ได้
อาวุธ ที่ใช้ฆ่าในที่นี้ก็คือ options ของคำสั่ง kill(1) นั่นเอง ดังนี้แล้ว โดยเนื้อแท้แล้ว
รูปแบบของคำสั่งทั่วๆไปคือ

# kill -option PID

อาวุธที่ฆ่าได้ตายสนิทคือ 9 ซึ่งแทบจะทุก process เมื่อเจอ option นี้เข้า หนีไม่รอด ตายถาวร ตายสนิท

# kill -9 pid

แทบจะทุก pid ที่เราเป็นเจ้าของ ถูกฆ่า หรือ หยุดแน่นอน

มีเรื่องขำๆที่เกี่ยวกับ process อยู่ก็คือการสั่งให้ process ใด process หนึ่ง หยุด, วิ่ง หรือ พักการทำงานก่อนชั่วขณะ
เรื่องมีอยู่ว่าในระบบปฏิบัติการระบบหนึ่ง มี process ที่กำลังวิ่งอยู่ขณะนั้นหลาย processes แหละ และตัวจัดการกับลำดับของ processes ต่างๆ เขาก็เรียงลำดับไว้อย่างดีว่า หมายเลขไหน ควรจะได้รับลำดับสูง หมายเลขไหน ควรจะชลอ ฯลฯ
ขณะนั้นเอง process A เขาก็ร้องว่า นี่งานด่วนเลยนะ เส้นใหญ่ด้วย ระดับ kernel น้า ฯลฯ
ฝ่ายผู้จัดการ process เขาก็บอกว่า เออ เดี๋ยวจะดูให้ว่ามีใครอู้งานมั่ง ก็พอดีเจอว่า process E แทบไม่ได้ทำอะไรสลักสำคัญนัก แต่ว่าเอาแค่ขยันโชว์ผลงานให้เจ้านาย ผู้จัดการ process เห็นดังนั้นจึงบอกกับ process E ว่า

'นี่ๆ ไปนอนก่อนได้ไหม จะได้มีที่ว่างให้น้องเอ (process A) เขาทำงานมั่ง'

เมื่อสั่งแล้วก็ไม่ได้ดูว่าเขาจะทำตามหรือไม่ เอาแต่ไปจัดการต่างๆเพื่อให้น้องเอได้ทำงาน
ฝ่าย process E เมื่อรับคำสั่งก็นึกในใจว่า


'อืมม ก็เราไม่ง่วงนี่หว่า จะไปนอนทำไม' ว่าแล้วก็ง่วนกับงานของตัวเองต่อไปเรื่อยๆ

น้องเอ เมื่อจบงานด่วนแล้วก็แจ้งกับ ผู้จัดการ process ว่า พี่ๆงานเสร็จเรียบร้อยดีแล้วค่า ขอบใจน้า
ข้างฝ่าย ผจก. ก็พยักหน้ารับทราบ แล้วมาตรวจดูว่า อืมม ใครนะควรจะได้รับให้วิ่งต่อไป ก็พบว่าตนเองสั่งให้ คุณ E ไปนอน ก็เลยไปปลุก

'น้องอีๆ ตื่นๆๆ ตื่นมาทำงานต่อ'
'อ้าว ก็ฉันไม่ได้นอนนี่ จะไปตื่นทำไม'
น้องอีตอบ
'แล้วนี่ก็ทำงานแทบตายอยู่แล้ว มาสั่งอะไรกันนักกันหนา ฮึ'
'เฮ้ยๆ แล้วนั่นทำอะไรไปละนั่น ยุ่งละซิทีนี้'

เอาแล้วซิ ทีนี้ก็ไปกันใหญ่แล้วหละ เพราะไม่รู้เหมือนกันว่า process ที่ไม่สามารถควบคุมได้นั้น จะสร้างความเสียหายให้กับระบบไว้ที่ไหน อย่างไรบ้าง

View My Stats