หน้าเว็บ

วันจันทร์ที่ 29 พฤศจิกายน พ.ศ. 2553

คำสั่งเปลี่ยนชื่อ Table ใน MySQL

ตรงตัวครับ คำสั่งเปลี่ยนชื่อ Table ใน MySQL สำหรับเวลาที่สร้าง Table เสร็จแล้วต้องการเปลี่ยนชื่อในภายหลัง

RENAME TABLE oldtablename TO newtablename


ระบบที่ทดสอบ

MySQL: 5.1.49

วันเสาร์ที่ 16 ตุลาคม พ.ศ. 2553

Middle Scrolling ของ Thinkpad บน Ubuntu 10.10 Maverick

ให้ลง package ที่ชื่อว่า gpointing-device-settings

sudo apt-get install gpointing-device-settings

เมื่อลงเสร็จบางคนอาจจะสามารถทำ middle scrolling ได้เลย แต่ถ้าไม่ได้ให้สั่ง

gpointing-device-settings

แล้วให้เลือก Use wheel emulation
แล้วให้อยากให้มัน Scroll แนวตั้งหรือแนวนอนได้ก็ให้เลือก Enable vertical/horizontal scroll ตามต้องการ

เวลาใช้งานก็กดกลางค้างไว้ แล้วลาก track point ขึ้นลงหรือซ้ายขวาตามต้องการ

ระบบที่ทดสอบ
OS: Ubuntu 10.10 Maverick

ที่มา
http://psung.blogspot.com/2010/09/thinkpad-trackpoint-scrolling-in-ubuntu.html

วันอาทิตย์ที่ 10 ตุลาคม พ.ศ. 2553

แก้ปัญหา compile Android Error Debug Certificate Expired

ถ้าใครลง Android แล้วพอคอมไพล์เกิดปัญหาคล้ายๆดังนี้

[2010-10-10 00:07:56 - Test] ERROR: Unable to open class file /path/to/androidproject/gen/com/example/androidproject/R.java: No such file or directory\R.java: No such file or directory
[2010-10-10 00:07:56 - Test] ERROR: Error generating final archive: Debug certificate expired on dd/MM/yyyy


ให้แก้โดยไปที่ ~/.android/ แล้วลบ debug.keystore ทิ้งซะ แล้วให้ทำการสร้างใหม่ด้วยคำสั่ง

%JAVA_HOME%\bin\keytool -genkey -keypass android -keystore debug.keystore -alias androiddebugkey -storepass android -validity 100000 -dname "CN=Android Debug,O=Android,C=US"

โดย %JAVA_HOME% คือ path ชี้ไปยังที่อยู่ของ jdk เช่น /usr/lib/jvm/java-6-sun เป็นต้น

เสร็จแล้วให้ลองปิด eclipse แล้วเปิดใหม่
แล้ว clean project แล้ว build ใหม่

ระบบที่ทดสอบ
OS: Ubuntu 10.04
IDE: Eclipse 3.5.2
AndroidSDK: 7 (2.1)

ที่มา
http://www.board.esanupdate.com/index.php/topic,5308.0.html

วันพุธที่ 11 สิงหาคม พ.ศ. 2553

เปลี่ยนให้ MySQL รองรับ remote connection

โดยค่าปริยาย (default) แล้ว MySQL จะทำการฟังที port 3306 เฉพาะ localhost (127.0.0.1) เท่านั้น ถ้าต้องการให้รองรับ connection จาก host อื่นจะทำไม่ได้

วิธีการคือให้ไปแก้ไฟล์ /etc/mysql/my.cnf แล้วทำการ comment บรรทัด bind-address ทิ้ง

#bind-address = 127.0.0.1

หลังจากนั้นก็ให้ restart MySQL Server

sudo service mysql restart

ระบบที่ทดสอบ
OS: Ubuntu 10.04
MySQL: 5.1.41

ที่มา
http://www.howtogeek.com/howto/mysql/switch-mysql-to-listen-on-tcp/

วันจันทร์ที่ 9 สิงหาคม พ.ศ. 2553

ใช้ printf library กับ TinyOS ผ่าน SerialForwarder

วันนี้ผมลองใช้ MoteLab ของ Harvard เพื่อจะทำการทดลองโปรแกรม TinyOS บนอุปกรณ์จริงจำนวนมาก ซึ่งผมลองดูตัวอย่างโค้ดของทาง MoteLab นั้นจะแสดงวิธีการเรียกค่าเก็บไว้ใน Message ที่ส่งผ่าน Master Serial Port ของทาง MoteLab

แต่ปัญหาต่อมาของผมคือตัวอย่างเหล่านั้นเป็นการส่งค่าประเภทที่เป็นตัวเลข ไม่ใช่ array และไม่ใช่ string ซึ่งที่ผมต้องการนั้นผมอยากจะใช้ library printf ของ TinyOS เพื่อแสดง String (ซึ่งเป็น array ของ char) แล้วส่งผ่านออกมาทาง Serial Port

ดังนั้นวิธีการของผมคือลองแกะโค้ดตัวอย่างของเค้าก่อนว่ามันต้องใช้ utility อะไรมาช่วยบ้าง ซึ่งโค้ดเค้านั้นเป็นภาษา python และมีการเรียกใช้ TestSerialMsg.py ซึ่งเป็น class ที่เก็บโครงสร้าง Message ที่ต้องการเอาไว้ ดังนั้นทำให้ผมพอจะเดาได้ว่าเราต้องมีการสร้าง PrintfMsg.py ขึ้นมาเพื่อใช้จัดการกับ Message ของไลบรารี printf ที่จะถูกส่งออกมา

ผมลองดู TestSerialMsg.py แล้วพบว่า class นั้นถูกสร้างมาจาก MIG ซึ่งใช้ในการ generate คลาสสำหรับโครงสร้าง Message นั้น แต่ว่าที่ผมเคยลองทำคือเอามา generate ออกมาเป็น .class ของภาษา java เท่านั้น ซึ่งตอนนั้นทำใน Makefile

ผมเลยลองสั่ง mig ดิบๆใน shell ดูก็พบว่ามันมี option ที่รองรับภาษา python ด้วย ดังนั้นผมจึงเริ่มไปไฟล์ที่เป็น structure ของ Message เริ่มต้นที่เป็นภาษา nesC ก่อน ก็พบว่ามันอยู่ที่ $(TOSROOT)/tos/lib/printf/printf.h

ดังนั้นก็ให้ไปที่ $(TOSROOT)/tos/lib/printf แล้วสั่งคำสั่งดังนี้

mig python -python-classname=PrintfMsg printf.h printf_msg -o PrintfMsg.py

จะได้ไฟล์ PrintfMsg.py ซึ่งไฟล์คลาสที่เก็บโครงสร้างของ Message แบบภาษา python ออกมา

ซึ่ง String นั้น Message นี้จะเก็บอยู่ตัวแปรอาเรย์ที่ชื่อ buffer ดังนั้นผมจึงลองไปดูที่ฟังก์ชัน getString_buffer() ที่ generate ออกมา และพบว่ามัน generate ผิด ไม่สามารถเรียกใช้ได้เพราะจะเกิด index out of bound นอกจากนั้นค่าที่ได้ยังไม่ใช่ String อีกด้วย โดยผมทำการแก้ไข 3 จุด คือ 1. เปลี่ยนขอบเขตเป็น 28 (จริงๆแล้วขึ้นค่า PRINTF_MSG_LENGTH ที่ define ไว้ใน printf.h) 2. ทำการจัดรูปเป็นเลขฐาน 16 แบบ 2 หลัก 3. ทำการแปลงเลขฐาน 16 ให้เป็น ascii character ซึ่งสุดท้ายแล้วฟังก์ชัน getString_buffer จะได้เป็นแบบนี้

import tinyos.message.Message
import binascii
...
...
def getString_buffer(self):
carr = "";
#for i in range(0, 4000):
for i in range(0, 28):
if self.getElement_buffer(i) == chr(0):
break
c = "%x" % (self.getElement_buffer(i) & 0xFF)
if (len(c) < 2):
carr += "0" + c
else:
carr += c
return binascii.unhexlify(carr)

*หมายเหตุ blog ผม indent มันเพี้ยน เวลาใช้จริงอย่าลืมจัด indent ให้ถูกต้อง

คราวนี้เวลานำไปใช้ก็ให้ลองดูตามตัวอย่าง TestSerial.py ของเค้า แล้วให้เพ่ิม

import PrintfMsg

แล้วเพิ่ม

self.mif.addListener(self, PrintfMsg.PrintfMsg)

และเวลาเรียกค่าออกมาให้ใช้

s = m.getString_buffer()

ก็จะได้ String ที่เกิดจากไลบรารี printf แล้วครับ แต่ว่าจะมีปัญหาเล็กน้อยคือถึงแม้เรา printf ออกมาเป็น String ยาวๆ แต่ว่าการส่งข้อมูลออกมาแต่ละครั้งจะเท่ากับความยาวที่กำหนดไว้เท่านั้น (ค่า default คือ 28) ดังนั้นมันจะตัดส่งออกมาทีละ 28 ตัวอักษร ถ้าต้องการให้มากกว่านั้นก็ลองไป compile ไลบรารี Printf กันใหม่ได้ครับ

ถ้าใครยังไม่เคยใช้ MoteLab เดี๋ยวว่างๆผมจะมาเขียนวิธีไว้ด้วยครับ

ระบบที่ทดสอบ
OS: Ubuntu 10.04
TinyOS: 2.1.1
Device: Harvard MoteLab

วันอาทิตย์ที่ 1 สิงหาคม พ.ศ. 2553

เพิ่ม System Call ใน Linux Kernel

อันนี้เป็นวิธีจากตำราเลยครับ แต่ว่าปรับให้ใช้กับ Kernel 2.6.34.1
(blog นี้ assume ว่าสามารถ compile kernel เป็นแล้ว)

สมมติว่าจะเพิ่ม system call ที่ชื่อ hellokernel ซึ่งทำหน้าที่ print คำว่า "hello kernel!" ออกมาเก็บใน log ไฟล์
1. สร้างไฟล์ hellokernel.c ไว้ใน /usr/src/linux-2.6.34.1/kernel
#include <linux/linkage.h>
#include <linux/kernel.h>
asmlinkage int sys_hellokernel() {
printk(KERN_EMERG "hello kernel!");
return 1;
}


2. เพิ่มเลขของ system call ใหม่ในไฟล์ /usr/src/linux-2.6.34.1/include/asm-generic/unistd.h
- ให้ค้นหาคำว่า "#undef __NR_syscalls" แล้วบรรทัดก่อนบรรทัดนี้ให้เติม
#define __NR_hellokernel 244
__SYSCALL(__NR_hellokernel, sys_hellokernel)

โดยตัวเลข 244 นั้นให้ดูว่า system call ตัวก่อนหน้านั้นเป็นเบอร์อะไร (ของผมเป็น __NR_recvmmsg 243) ก็ให้เอาเลขนั้นบวก 1
- และบรรทัดต่อจากนั้น #define __NR_syscalls นั้นให้บวก 1 เข้าไป (ของเดิมของผมเป็น 244 ก็เปลี่ยนเป็น 245)

3. แก้ไขไฟล์ /usr/src/linux-2.6.34.1/arch/x86/kernel/syscall_table_32.S (สำหรับกรณีเครื่อง x86 ถ้าเป็นเครื่องอื่นก็แก้ที่โฟลเดอร์ของ arch นั้นๆ)
- เพิ่ม .long sys_hellokernel ไว้ที่ท้ายสุดของไฟล์ต่อลงมา

4. แก้ไข Makefile ใน /usr/src/linux-2.6.34.1/kernel
- เพิ่ม hellokernel.o ให้กับ obj-y (ต่อท้ายสุดก็ได้)
เรียบร้อยแล้วให้ทำการคอมไพล์ Kernel ใหม่ แล้ว boot เข้า kernel ที่ใหม่นี้ แล้วทดสอบโดยการสร้างไฟล์ test.c ขึ้นมา
#include <linux/unistd.h>
#define __NR_hellokernel 244 // 244 แทนเลขของ system call ที่ประกาศไว้ข้างบน

main() {
syscall(__NR_hellokernel);
}

เสร็จแล้วก็ลอง compile แล้ว run ดู ถ้าสำเร็จจะมีข้อความ "hello kernel!" ปรากฏอยู่ใน log file ของ kernel ที่ /var/log/kernel/warnings

ระบบที่ทดสอบ
OS: Ubuntu 10.04
Kernel: Linux Kernel 2.6.34.1

อ้างอิงหนังสือ Operating System Concepts 8th Edition, A. Silberschatz, P. B. Galvin, and G. Gagne

วันเสาร์ที่ 31 กรกฎาคม พ.ศ. 2553

วิธี Compile Linux kernel 2.6 บน Ubuntu 10.04

ในบางคราวเราอาจจะต้องคอมไพล์ Linux Kernel เพื่อเพิ่มฟังก์ชันอะไรบางอย่าง หรือเพื่ออยากรู้อยากลองก็มีวิธีการดังต่อไปนี้ครับ (ผมทำบน Ubuntu 10.04)
1. ดาวน์โหลด source code ของ kernel มาก่อน โดยสามารถดาวน์โหลดได้ที่ http://www.kernel.org/ โดยที่ผมทำจะใช้เป็นรุ่น 2.6.34.1 ครับ
แตกไฟล์แล้วเอาโฟลเดอร์ linux-2.6.34.1 ไปไว้ใน /usr/src ซึ่งเป็นโฟลเดอร์ที่นิยมใช้เก็บ source ของ kernel

2. เตรียมเครื่องมือ ได้แก่ kernel-package, fakeroot, ncurses (อันไหนมีแล้วก็ไม่ต้องโหลดเพิ่ม แต่ถ้าอันไหนมันฟ้องว่ายังขาดก็โหลดเพิ่มนะครับ :P)
sudo apt-get install kernel-package fakeroot libncurses5-dev

3. ทำการ configure kernel
ไปที่โฟลเดอร์ source ของเรา /usr/src/linux-2.6.34.1 แล้วสั่ง configure โดยสั่งได้ 3 รูปแบบ
วิธีแรกเป็นแบบ text-based
make menuconfig

วิธีที่สองถ้ามี Qt
make xconfig

วิธีที่สามถ้ามี Gtk
make gconfig

ก็เลือกตามสะดวกครับ ถ้าคิดไม่ออกก็เลือกวิธีแรกก็ได้
โดยใน menu สำหรับ configure นั้นจะมีอะไรให้เราเลือกมากมายครับก็เลือกตามที่ต้องการ แต่ถ้าไม่แน่ใจว่าคืออะไรก็ปล่อยเป็นค่า default ก็ได้ครับ

4. Compile Kernel
ในกรณีถ้าเครื่องมีหลาย cpu และต้องการให้คอมไพล์เร็วขึ้นให้สั่ง
export CONCURRENCY_LEVEL=3
โดยตัวเลขให้ใช้ จำนวนcpuที่มี + 1 (ในกรณีนี้ผมมี 2 cpu (2 core) เลยเป็น 3)

แล้วสั่ง
make-kpkg clean
fakeroot make-kpkg --initrd --append-to-version=-some-string-here kernel-image kernel-headers

โดย -some-string-here ใส่เป็นอะไรก็ได้เพื่อบอก version ของเรา เช่นของผมจะใส่ว่า -ping2p (ต้องขึ้นต้นด้วยเครื่องหมาย - และห้ามมีเว้นวรรค)

แล้วก็รอมันคอมไพล์ไป ระหว่างนี้ก็ไปอาบน้ำ อ่านหนังสือ กินข้าว รอจนกว่ามันจะเสร็จนะครับ ถ้าเสร็จแล้วลองดูที่โฟลเดอร์ /usr/src จะมีไฟล์ 2 ไฟล์คือ linux-image-2.6.34.1-ping2p_2.6.34.1-ping2p-10.00.Custom_i386.deb และ linux-headers-2.6.34.1-ping2p_2.6.34.1-ping2p-10.00.Custom_i386.deb (ในกรณีที่ compile แล้ว error เพราะ permission denied ให้ลองเปลี่ยน permission ของโฟลเดอร์ /usr/src ให้สามารถ write ได้ แล้วลองคอมไพล์ใหม่อีกรอบ (แต่จะใช้เวลาไม่นานเหมือนครั้งแรก เพราะหลายๆอย่างคอมไพล์เสร็จแล้ว))

5. Install
คราวนี้ก็จะทำการ Install kernel ใหม่นี้ โดยทำเป็น Option ให้เลือกตอน boot เผื่อเกิดอะไรผิดพลาดจะได้เรียกของเก่ากลับมาได้
ไปที่โฟลเดอร์ /usr/src จะพบ kernel ใหม่ที่เราคอมไพล์ แล้วให้ทำการติดตั้งดังนี้
sudo dpkg -i linux-image-2.6.34.1-ping2p_2.6.34.1-ping2p-10.00.Custom_i386.deb
sudo dpkg -i linux-headers-2.6.34.1-ping2p_2.6.34.1-ping2p-10.00.Custom_i386.deb


*** ในกรณี Ubuntu 10.04 จะมี bug โดยไม่ยอม initramfs มาให้ ให้สร้างเอง โดยในโฟลเดอร์ /usr/src ให้สั่ง sudo update-initramfs -c -k 2.6.34.1-ping2p (ใส่ version และชื่อตามรุ่นที่เราคอมไพล์และตั้งชื่อไว้ตอนแรก) เสร็จแล้วให้ลองตรวจสอบใน /boot ดูจะมีไฟล์ initrd.img2.6.34.1-ping2p, System.map-2.6.34.1-ping2p และ vmlinuz-2.6.34.1-ping2p ออกมา

6. ตรวจสอบ Bootloader
เพื่อให้แน่ใจว่าตอน boot แล้วจะมี kernel ใหม่ให้เลือก ให้ลองตรวจสอบ bootloader ดู ซึ่งแล้วแต่ว่า bootloader เป็น grub หรือ lilo
ในกรณีของผมเป็น grub2 ก็ไปดูที่ไฟล์ /boot/grub/grub.cfg (แต่ถ้าเป็น grub 1 จะอยู่ใน /boot/grub/menu.lst) จะมี kernel ใหม่อยู่

*** ลองตรวจสอบว่าตรงรายการ kernel ใหม่นั้นมีบรรทัด initrd /boot/initrd.img-2.6.34.1-ping2p อยู่หรือไม่ ถ้าไม่มีให้ใส่เพิ่มเข้าไป (ตัวที่เป็น recovery mode ก็เช่นกันให้ใส่เข้าไปด้วย) ส่วนบรรทัดที่ขึ้นต้นด้วย linux /boot/vmlinuz-2.6.34.1-ping2p ให้ลองเปลี่ยนค่า root=/dev/sda5 เป็น root=UUID=..... โดยค่า UUID ให้ใช้ค่าที่อยู่ใน option --fs-uuid --set .... ที่อยู่ในบรรทัดข้างบน เช่นของผมจะเป็น
menuentry 'Ubuntu, with Linux 2.6.34.1-ping2p' --class ubuntu --class gnu-linux --class gnu --class os {
recordfail
insmod ext2
set root='(hd0,5)'
search --no-floppy --fs-uuid --set 54c8e93d-971f-4197-8a08-b9e131d1becf
linux /boot/vmlinuz-2.6.34.1-ping2p root=UUID=54c8e93d-971f-4197-8a08-b9e131d1becf ro quiet splash
initrd /boot/initrd.img-2.6.34.1-ping2p
}


เป็นอันเรียบร้อยครับ ลอง reboot ดู ตัว bootloader ของเราจะมี option kernel ตัวใหม่ของเราอยู่ด้วย

ระบบที่ทดสอบ
OS: Ubuntu 10.04
Kernel: Linux 2.6.34.1


อ้างอิง
http://www.howtoforge.com/kernel_compilation_ubuntu
http://linuxtweaking.blogspot.com/2010/05/how-to-compile-kernel-on-ubuntu-1004.html
http://www.cyberciti.biz/tips/compiling-linux-kernel-26.html