Wednesday, November 04, 2009

解決在 Busybox中 ctrl+c 沒有作用的問題

最近在公司弄 embedded linux 的東西,
boot 完 kernel 進到 busybox 後,
發現 ctrl+c 竟然沒有作用(沒有 ctrl+c真的很不方便),
我們可以看一下當ctrl+c 按下所經過的路徑

driver/char/n_tty.c :
n_tty_receive_buf() -->
n_tty_receive_break() -->
isig(SIGINT,tty,1)-->

kernel/signal.c :
kill_pgrp(tty->pgrp, SIGINT, 1)-->
kill_pgrp_info(SIGINT, __si_special(priv), pid)-->

最後會中斷每個 group number 為 tty->pgrp的task,
只要process具有相同的group id
不管 background / foreground 都會被 kill 掉,
ctrl+c是傳送到 /dev/ttyS0 driver 的,
在原本的 root file system 並沒有 ttyS0 這個 device node,
使用的是 /dev/console 這個 device
後來在 busybox 網站  FAQ 查到

http://www.busybox.net/FAQ.html#job_control

Job control will be turned off since your shell can not obtain a controlling terminal. This typically happens when you run your shell on /dev/console. The kernel will not provide a controlling terminal on the /dev/console device. Your should run your shell on a normal tty such as tty1 or ttyS0 and everything will work perfectly. If you REALLY want your shell to run on /dev/console, then you can hack your kernel (if you are into that sortof thing) by changing drivers/char/tty_io.c to change the lines where it sets "noctty = 1;" to instead set it to "0". I recommend you instead run your shell on a real console... 

解決方法如下

第一種方法
1. 在 dev 目錄下建立 ttyS0 device node, 將 console link 到 ttyS0

#mknod --mode 666 ttyS0 c 4 64
#ln -s ttyS0 console


2. 修改 /etc/inittab

#vi /etc/inittab
console::sysinit:-/etc/rcS
ttyS0::respawn:-/bin/sh


第二種方法
Hack kernel
修改 drivers/char/tty_io.c
將 noctty = 1 的地方改為 noctty = 0
然後 /etc/inittab 就可以寫成
console::sysinit:-/etc/rcS
console::respawn:-/bin/sh

重新製作 root file system 測試果然 ok了
 
不過 busybox 的建議是在 real console 下 run shell ....

Monday, November 02, 2009

BUG_ON(size & (size - 1));

今天看 Linux kernel 中 kfifo (circular buffer) 的 code, 無意間看到一行code


/* size must be a power of 2 */
BUG_ON(size & (size - 1));

這真是個好用的判断技巧