For raid : 1. The following is how to create Ubuntu live USB: http://blog.xuite.net/yh96301/blog/57645340-%E5%85%8D%E8%B2%BB%E8%A3%BD%E4%BD%9CUbuntu+Live+USB%E9%96%8B%E6%A9%9F%E9%9A%A8%E8%BA%AB%E7%A2%9F%E7%9A%84%E8%BB%9F%E9%AB%94unetbootin 2. check the raid device id : When "df -h", will see the following raid partitions: /dev/mapper/isw_dcgajhgdje_Volume0p1 (/) /dev/mapper/isw_dcgajhgdje_Volume0p5 (/home) The "/dev/mapper/isw_dcgajhgdje_Volume0" is raid id. 3. After enter Ubuntu live USB: mkdir /mnt/sda mount /dev/mapper/isw_dcgajhgdje_Volume0p1 /mnt/sda mount --bind /proc /mnt/sda/proc mount --bind /dev /mnt/sda/dev chroot /mnt/sda grub-install /dev/mapper/isw_dcgajhgdje_Volume0p
2013年7月4日 星期四
How to recovery MBR
2011年9月20日 星期二
real time, user time, sys time of a process
針對一個process的時間統計:
real==>指逝去的時間(elapsed time)(time of waiting for I/O to complete + time used by other processes)(透過gettimeofday()或times()收集)
user==>指CPU執行該process的user-mode code的時間(透過 times()收集)
sys==>指CPU執行該process的kernel-mode code的時間(透過times()收集)
User+Sys==>指CPU真正執行該procees的時間(可透clock()收集)
http://www.gnu.org/s/hello/manual/libc/CPU-Time.html#CPU-Time
http://osr600doc.sco.com/en/SDK_c++/_Measuring_Program_Execution_Tim.html
#include stdio.h
#include time.h
#include sys/param.h
#include sys/times.h
#include sys/types.h
int main(){
int i;
struct tms t,u;
long r1,r2;
struct timeval start, end;
clock_t start_c, end_c;
gettimeofday(&start, NULL);
r1 = times(&t);
start_c=clock();
for(i=0;i < 10000 ;i++){
printf("hello!!\n");
}
end_c=clock();
r2 = times(&u);
gettimeofday(&end, NULL);
printf("\nHZ=%d\n",HZ);
printf("user time=%f\n",((float)(u.tms_utime-t.tms_utime))/(HZ));
printf("system time=%f\n",((float)(u.tms_stime-t.tms_stime))/(HZ));
printf("real time=%f\n",((float)(r2-r1))/(HZ));
printf("real time(gettimeofday())=%f\n", (float)((end.tv_sec * 1000000 + end.tv_usec)- (start.tv_sec * 1000000 + start.tv_usec))/1000000);
printf("user+real=%f\n" ,((double) (end_c - start_c)) / CLOCKS_PER_SEC);
return 0;
}
output:
hello!!
.....
hello!!
HZ=100
user time=0.000000
system time=0.020000
real time=0.150000
real time(gettimeofday())=0.151931
user+real=0.020000
clock()的實作:
#include sys/times.h
#include sys/param.h
#include time.h
#include unistd.h
clock_t clock(void) {
struct tms buf;
times(&buf);
#if CLOCKS_PER_SEC == HZ
return (unsigned long) buf.tms_utime + buf.tms_stime;
#elif CLOCKS_PER_SEC % HZ == 0
return ((unsigned long) buf.tms_utime + buf.tms_stime) * (CLOCKS_PER_SEC / HZ);
#elif HZ % CLOCKS_PER_SEC == 0
return ((unsigned long) buf.tms_utime + buf.tms_stime) / (HZ / CLOCKS_PER_SEC);
#else
return ((unsigned long long) buf.tms_utime + buf.tms_stime) * CLOCKS_PER_SEC / HZ;
#endif
}
real==>指逝去的時間(elapsed time)(time of waiting for I/O to complete + time used by other processes)(透過gettimeofday()或times()收集)
user==>指CPU執行該process的user-mode code的時間(透過 times()收集)
sys==>指CPU執行該process的kernel-mode code的時間(透過times()收集)
User+Sys==>指CPU真正執行該procees的時間(可透clock()收集)
http://www.gnu.org/s/hello/manual/libc/CPU-Time.html#CPU-Time
http://osr600doc.sco.com/en/SDK_c++/_Measuring_Program_Execution_Tim.html
#include stdio.h
#include time.h
#include sys/param.h
#include sys/times.h
#include sys/types.h
int main(){
int i;
struct tms t,u;
long r1,r2;
struct timeval start, end;
clock_t start_c, end_c;
gettimeofday(&start, NULL);
r1 = times(&t);
start_c=clock();
for(i=0;i < 10000 ;i++){
printf("hello!!\n");
}
end_c=clock();
r2 = times(&u);
gettimeofday(&end, NULL);
printf("\nHZ=%d\n",HZ);
printf("user time=%f\n",((float)(u.tms_utime-t.tms_utime))/(HZ));
printf("system time=%f\n",((float)(u.tms_stime-t.tms_stime))/(HZ));
printf("real time=%f\n",((float)(r2-r1))/(HZ));
printf("real time(gettimeofday())=%f\n", (float)((end.tv_sec * 1000000 + end.tv_usec)- (start.tv_sec * 1000000 + start.tv_usec))/1000000);
printf("user+real=%f\n" ,((double) (end_c - start_c)) / CLOCKS_PER_SEC);
return 0;
}
output:
hello!!
.....
hello!!
HZ=100
user time=0.000000
system time=0.020000
real time=0.150000
real time(gettimeofday())=0.151931
user+real=0.020000
clock()的實作:
#include sys/times.h
#include sys/param.h
#include time.h
#include unistd.h
clock_t clock(void) {
struct tms buf;
times(&buf);
#if CLOCKS_PER_SEC == HZ
return (unsigned long) buf.tms_utime + buf.tms_stime;
#elif CLOCKS_PER_SEC % HZ == 0
return ((unsigned long) buf.tms_utime + buf.tms_stime) * (CLOCKS_PER_SEC / HZ);
#elif HZ % CLOCKS_PER_SEC == 0
return ((unsigned long) buf.tms_utime + buf.tms_stime) / (HZ / CLOCKS_PER_SEC);
#else
return ((unsigned long long) buf.tms_utime + buf.tms_stime) * CLOCKS_PER_SEC / HZ;
#endif
}
2011年9月6日 星期二
##巨集定義的用法
/*
~/tmp$ gcc -D_CACHE=arm920 -g -static -o test test.c
~/tmp$ ./test
call arm920_dma_flush_range()!!
~/tmp$ gcc -D_CACHE=arm926 -g -static -o test test.c
~/tmp$ ./test
call arm926_dma_flush_range()!!
~/tmp$
*/
#include
#define ____glue(name,fn) name##fn
#define __glue(name,fn) ____glue(name,fn)
void arm926_dma_flush_range(){
printf("call arm926_dma_flush_range()!!\n");
}
void arm920_dma_flush_range(){
printf("call arm920_dma_flush_range()!!\n");
}
#define dmac_flush_range __glue(_CACHE,_dma_flush_range)
int main()
{
dmac_flush_range();
return 0;
}
~/tmp$ gcc -D_CACHE=arm920 -g -static -o test test.c
~/tmp$ ./test
call arm920_dma_flush_range()!!
~/tmp$ gcc -D_CACHE=arm926 -g -static -o test test.c
~/tmp$ ./test
call arm926_dma_flush_range()!!
~/tmp$
*/
#include
#define ____glue(name,fn) name##fn
#define __glue(name,fn) ____glue(name,fn)
void arm926_dma_flush_range(){
printf("call arm926_dma_flush_range()!!\n");
}
void arm920_dma_flush_range(){
printf("call arm920_dma_flush_range()!!\n");
}
#define dmac_flush_range __glue(_CACHE,_dma_flush_range)
int main()
{
dmac_flush_range();
return 0;
}
2010年6月2日 星期三
Some constant varible defined in kernel about executing user-space programs
Some constant varible defined in kernel about executing user-space programs.
_STK_LIM(include/linux/resource.h)(stack size):Define the stack size limitation. In a standard kernel, the value is 8MB
STACK_TOP ()(stack pointer):Define the stack pointer. In a standard kernel, the value is TASK_SIZE.
PAGE_OFFSET(arch/arm/include/asm/memory.h):Define the virtual address of the start of the kernel image. In a standard kernel, the value is 0xC0000000(CONFIG_PAGE_OFFSET).
TASK_SIZE(arch/arm/include/asm/memory.h)(process address space size):Define the maximum size of a user space task. In a standard kernel, the value is 0xBF000000(PAGE_OFFSET-0x01000000)
TASK_UNMAPPED_BASE(the start virtual address of shared libaries mapping region): Define the lower boundary of the mmap VM area. The area also is memory mapped region for shared libraries. Because the program interpreter (/lib/ld-2.X.X.so for glibc, /lib/ld-uClibc-0.9.29.so for uClibc) will use mmap() to let the shared libraries file map to the area. In a standard kernel, the value is 0x40000000(PAGE_OFFSET / 3).
When appling the FCSE patch (http://sisyphus.hd.free.fr/~gilles/pub/fcse/downloads/fcse-2.6.33-v4.patch.bz2), the varibes described as mentioned above will be changed:
_STK_LIM will be 1MB
TASK_SIZE will be 0x02000000 (32 MB)
STACK_TOP will at 0x02000000 (TASK_SIZE)
TASK_UNMAPPED_BASE will at 0x00800000 (8M)
According to our requirement, we can use "ulimit -s $new_stack_size" to increase or decrease the stack size.(http://www.mail-archive.com/openmoko-kernel@lists.openmoko.org/msg10517.html)
The heap region will follow process image region. The following is the process address space of "venc" (cat /proc/959/maps | more):
00008000-00025000 r-xp 00000000 01:00 213 /usr/sbin/venc
0002c000-0002e000 rwxp 0001c000 01:00 213 /usr/sbin/venc
0002e000-003fa000 rwxp 0002e000 00:00 0 [heap]
40000000-4000c000 r-xp 00000000 01:00 159 /lib/ld-uClibc-0.9.29.so
4000c000-40010000 rwxp 4000c000 00:00 0
40010000-40011000 rwxs 00000000 00:09 1441 /dev/vpl_vic0
40011000-40012000 rwxs 00000000 00:09 1441 /dev/vpl_vic0
40012000-40013000 rwxs 02424000 00:09 1337 /dev/vma_die
40013000-40014000 r-xp 0000b000 01:00 159 /lib/ld-uClibc-0.9.29.so
40014000-40015000 rwxp 0000c000 01:00 159 /lib/ld-uClibc-0.9.29.so
40015000-40017000 r-xp 00000000 01:00 400 /usr/lib/libbitmaskresizer.so.1.0.0.1
40017000-4001e000 ---p 40017000 00:00 0
4001e000-4001f000 rwxp 00001000 01:00 400 /usr/lib/libbitmaskresizer.so.1.0.0.1
4001f000-40022000 r-xp 00000000 01:00 399 /usr/lib/libdeinterlacer.so.3.0.0.3
40022000-40029000 ---p 40022000 00:00 0
40029000-4002a000 rwxp 00002000 01:00 399 /usr/lib/libdeinterlacer.so.3.0.0.3
4002a000-40046000 r-xp 00000000 01:00 373 /usr/lib/libexpat.so.0.5.0
40046000-4004d000 ---p 40046000 00:00 0
4004d000-4004f000 rwxp 0001b000 01:00 373 /usr/lib/libexpat.so.0.5.0
4004f000-40050000 r-xp 00000000 01:00 428 /usr/lib/libframeratectrl.so.1.0.0.0
40050000-40057000 ---p 40050000 00:00 0
40057000-40058000 rwxp 00000000 01:00 428 /usr/lib/libframeratectrl.so.1.0.0.0
40058000-4007e000 r-xp 00000000 01:00 376 /usr/lib/libfreetype.so.6.3.20
4007e000-40085000 ---p 4007e000 00:00 0
40085000-40086000 rwxp 00025000 01:00 376 /usr/lib/libfreetype.so.6.3.20
40086000-40091000 r-xp 00000000 01:00 379 /usr/lib/libh264enc.so.2.3.0.4
......
42a9c000-4329b000 rwxp 42a9c000 00:00 0
50000000-5010e000 rwxs 04000000 00:09 1217 /dev/vpl_edmc
5010e000-50fe3000 rwxs 0410e000 00:09 1217 /dev/vpl_edmc
50fe3000-50fe5000 rwxs 04fe2000 00:09 1217 /dev/vpl_edmc
50fe5000-50fe6000 rwxs 04fe3000 00:09 1217 /dev/vpl_edmc
......
641b0000-64233000 rwxs 14d81000 00:09 1217 /dev/vpl_edmc
be974000-be989000 rwxp befeb000 00:00 0 [stack]
One thing for using FCSE must be noted:
To utilize the FCSE, compile and link all programs to run in the first 32 MB block of virtual
memory (VA). (refer to "P.516, ARM System Developer’s Guide Designing and Optimizing System Software")
The start virtual address of executable ELF image compiled using the GNU toolchain for arm eabi is "0x00008000" (On X86, the address is "0x08048000"). (check "arm-eabi-uclibc/usr/lib/ldscripts/armelf_linux_eabi.xc")
The Execution process of program under linux:
1. 使用者在shell執行外部程式
2. shell以fork+exec syscall方式執行外部程式
3. 透過int 0x80軟體中斷觸發kernel的exec syscall服務 (sys_execvp)
4. exec syscall執行Program loader(ELF Loader),載入process image (ELF image)
5. Program loader找到PT_INTERP segment。
6. Program loader將PT_LOAD segment mapping為新的text/data segment
text segment 由虛擬位址0x0804_8000開始,data segment 緊接其後
7. Program loader呼叫interpreter loader將program interpreter (ld.so)載入,並mapping 到process
memory
interpreter的text segment由虛擬位址0x4000_0000開始,interpreter的data segment緊接其後
8. Program loader將BSS segment 準備好
9. Program loader將process 的 register %eip (user-mode)修改為program interpreter的進入點,並將%esp設定為user
mode的stack
10. Program interpreter會找到process所需的shared library(名稱與路徑)
11. Program interpreter透過mmap(2),將shared library予以mapping到process memory,以完成整個Process Image的建立
12. 更新 shared library 的符號表。
13. Program interpreter執行x86 jump動作,到process的進入點
紀錄於ELF header的entry point
14. 程式正式執行
步驟 4.~9. 由 kernel 的 ELF loader 所負責。
步驟 11.~14 由 user-space 的 program interpreter(dynamic loader/linker,也就是 /lib/ld-linux.so.2)所負責。
Reference:
1. http://www.jollen.org/blog/2007/03/elf_program_loading_4_flow_chart.html
2. http://jserv.sayya.org/helloworld/
_STK_LIM(include/linux/resource.h)(stack size):Define the stack size limitation. In a standard kernel, the value is 8MB
STACK_TOP ()(stack pointer):Define the stack pointer. In a standard kernel, the value is TASK_SIZE.
PAGE_OFFSET(arch/arm/include/asm/memory.h):Define the virtual address of the start of the kernel image. In a standard kernel, the value is 0xC0000000(CONFIG_PAGE_OFFSET).
TASK_SIZE(arch/arm/include/asm/memory.h)(process address space size):Define the maximum size of a user space task. In a standard kernel, the value is 0xBF000000(PAGE_OFFSET-0x01000000)
TASK_UNMAPPED_BASE(the start virtual address of shared libaries mapping region): Define the lower boundary of the mmap VM area. The area also is memory mapped region for shared libraries. Because the program interpreter (/lib/ld-2.X.X.so for glibc, /lib/ld-uClibc-0.9.29.so for uClibc) will use mmap() to let the shared libraries file map to the area. In a standard kernel, the value is 0x40000000(PAGE_OFFSET / 3).
When appling the FCSE patch (http://sisyphus.hd.free.fr/~gilles/pub/fcse/downloads/fcse-2.6.33-v4.patch.bz2), the varibes described as mentioned above will be changed:
_STK_LIM will be 1MB
TASK_SIZE will be 0x02000000 (32 MB)
STACK_TOP will at 0x02000000 (TASK_SIZE)
TASK_UNMAPPED_BASE will at 0x00800000 (8M)
According to our requirement, we can use "ulimit -s $new_stack_size" to increase or decrease the stack size.(http://www.mail-archive.com/openmoko-kernel@lists.openmoko.org/msg10517.html)
The heap region will follow process image region. The following is the process address space of "venc" (cat /proc/959/maps | more):
00008000-00025000 r-xp 00000000 01:00 213 /usr/sbin/venc
0002c000-0002e000 rwxp 0001c000 01:00 213 /usr/sbin/venc
0002e000-003fa000 rwxp 0002e000 00:00 0 [heap]
40000000-4000c000 r-xp 00000000 01:00 159 /lib/ld-uClibc-0.9.29.so
4000c000-40010000 rwxp 4000c000 00:00 0
40010000-40011000 rwxs 00000000 00:09 1441 /dev/vpl_vic0
40011000-40012000 rwxs 00000000 00:09 1441 /dev/vpl_vic0
40012000-40013000 rwxs 02424000 00:09 1337 /dev/vma_die
40013000-40014000 r-xp 0000b000 01:00 159 /lib/ld-uClibc-0.9.29.so
40014000-40015000 rwxp 0000c000 01:00 159 /lib/ld-uClibc-0.9.29.so
40015000-40017000 r-xp 00000000 01:00 400 /usr/lib/libbitmaskresizer.so.1.0.0.1
40017000-4001e000 ---p 40017000 00:00 0
4001e000-4001f000 rwxp 00001000 01:00 400 /usr/lib/libbitmaskresizer.so.1.0.0.1
4001f000-40022000 r-xp 00000000 01:00 399 /usr/lib/libdeinterlacer.so.3.0.0.3
40022000-40029000 ---p 40022000 00:00 0
40029000-4002a000 rwxp 00002000 01:00 399 /usr/lib/libdeinterlacer.so.3.0.0.3
4002a000-40046000 r-xp 00000000 01:00 373 /usr/lib/libexpat.so.0.5.0
40046000-4004d000 ---p 40046000 00:00 0
4004d000-4004f000 rwxp 0001b000 01:00 373 /usr/lib/libexpat.so.0.5.0
4004f000-40050000 r-xp 00000000 01:00 428 /usr/lib/libframeratectrl.so.1.0.0.0
40050000-40057000 ---p 40050000 00:00 0
40057000-40058000 rwxp 00000000 01:00 428 /usr/lib/libframeratectrl.so.1.0.0.0
40058000-4007e000 r-xp 00000000 01:00 376 /usr/lib/libfreetype.so.6.3.20
4007e000-40085000 ---p 4007e000 00:00 0
40085000-40086000 rwxp 00025000 01:00 376 /usr/lib/libfreetype.so.6.3.20
40086000-40091000 r-xp 00000000 01:00 379 /usr/lib/libh264enc.so.2.3.0.4
......
42a9c000-4329b000 rwxp 42a9c000 00:00 0
50000000-5010e000 rwxs 04000000 00:09 1217 /dev/vpl_edmc
5010e000-50fe3000 rwxs 0410e000 00:09 1217 /dev/vpl_edmc
50fe3000-50fe5000 rwxs 04fe2000 00:09 1217 /dev/vpl_edmc
50fe5000-50fe6000 rwxs 04fe3000 00:09 1217 /dev/vpl_edmc
......
641b0000-64233000 rwxs 14d81000 00:09 1217 /dev/vpl_edmc
be974000-be989000 rwxp befeb000 00:00 0 [stack]
One thing for using FCSE must be noted:
To utilize the FCSE, compile and link all programs to run in the first 32 MB block of virtual
memory (VA). (refer to "P.516, ARM System Developer’s Guide Designing and Optimizing System Software")
The start virtual address of executable ELF image compiled using the GNU toolchain for arm eabi is "0x00008000" (On X86, the address is "0x08048000"). (check "arm-eabi-uclibc/usr/lib/ldscripts/armelf_linux_eabi.xc")
The Execution process of program under linux:
1. 使用者在shell執行外部程式
2. shell以fork+exec syscall方式執行外部程式
3. 透過int 0x80軟體中斷觸發kernel的exec syscall服務 (sys_execvp)
4. exec syscall執行Program loader(ELF Loader),載入process image (ELF image)
5. Program loader找到PT_INTERP segment。
6. Program loader將PT_LOAD segment mapping為新的text/data segment
text segment 由虛擬位址0x0804_8000開始,data segment 緊接其後
7. Program loader呼叫interpreter loader將program interpreter (ld.so)載入,並mapping 到process
memory
interpreter的text segment由虛擬位址0x4000_0000開始,interpreter的data segment緊接其後
8. Program loader將BSS segment 準備好
9. Program loader將process 的 register %eip (user-mode)修改為program interpreter的進入點,並將%esp設定為user
mode的stack
10. Program interpreter會找到process所需的shared library(名稱與路徑)
11. Program interpreter透過mmap(2),將shared library予以mapping到process memory,以完成整個Process Image的建立
12. 更新 shared library 的符號表。
13. Program interpreter執行x86 jump動作,到process的進入點
紀錄於ELF header的entry point
14. 程式正式執行
步驟 4.~9. 由 kernel 的 ELF loader 所負責。
步驟 11.~14 由 user-space 的 program interpreter(dynamic loader/linker,也就是 /lib/ld-linux.so.2)所負責。
Reference:
1. http://www.jollen.org/blog/2007/03/elf_program_loading_4_flow_chart.html
2. http://jserv.sayya.org/helloworld/
2010年5月30日 星期日
How to use sigsuspend() to wait the signal
//Reference:http://www.gnu.org/s/libc/manual/html_node/Sigsuspend.html#Sigsuspend
#include <&stdio.h&>
#include <&stdlib.h&>
#include <&string.h&>
#include <&unistd.h&>
#include <&signal.h&>
static int g_bTerminate=0;
static void register_signal(int signum, void (*handler)(int))
{
struct sigaction sigaInst;
sigset_t block_mask;
//Initializes the signal set set to include all of the defined signals.
sigfillset (&block_mask);
if(signum != SIGALRM)
{
sigaInst.sa_flags = SA_RESTART;
}
sigaInst.sa_handler = handler;
/*
sigset_t sa_mask
This specifies a set of signals to be blocked while the handler runs. Blocking is explained in Blocking for Handler. Note that the signal that was delivered is automatically blocked by default before its handler is started; this is true regardless of the value in sa_mask. If you want that signal not to be blocked within its handler, you must write code in the handler to unblock it.
*/
sigaInst.sa_mask=block_mask;
sigaction(signum, &sigaInst, NULL);
}
static void ctrl_sighandler(int signo)
{
printf("enter signal handler...!\n");
if (signo == SIGTERM)
{
g_bTerminate = 1;
}
}
int main(){
sigset_t mask, oldmask;
sigset_t block_mask;
//The user can use "kill -15 XXX" to terminate the progarm.
register_signal(SIGTERM, ctrl_sighandler);
sigemptyset(&block_mask);
//Block SIGQUIT (Terminal quit (POSIX)). The user can not use "Ctrl+\" to terminate the procgram.
sigaddset(&block_mask,SIGQUIT);
//Block SIGINT (Terminal interrupt (ANSI)). The user can not use "Ctrl+C" to terminate the procgram.
sigaddset(&block_mask, SIGINT);
sigprocmask (SIG_BLOCK, &block_mask, NULL);
/* Set up the mask of signals to temporarily block. */
sigemptyset (&mask);
sigaddset (&mask, SIGTERM);
//daemon(0, 0);
//Wait for SIGTERM arriving...
//1. temporarily block SIGTERM
sigprocmask (SIG_BLOCK, &mask, &oldmask);
while (g_bTerminate == 0)
sigsuspend (&oldmask);//2. SIGTERM is not in oldmask. So when one signal arrivies, sigsuspend() return. And then check g_bTerminate. If the signal is SIGTERM, the g_bTerminate will be set as 1. So the while-loop is break.
sigprocmask (SIG_UNBLOCK, &mask, NULL);//3. Remove SIGTERM from the block list.
printf("main() has been terminated....\n");
return 0;
}
#include <&stdio.h&>
#include <&stdlib.h&>
#include <&string.h&>
#include <&unistd.h&>
#include <&signal.h&>
static int g_bTerminate=0;
static void register_signal(int signum, void (*handler)(int))
{
struct sigaction sigaInst;
sigset_t block_mask;
//Initializes the signal set set to include all of the defined signals.
sigfillset (&block_mask);
if(signum != SIGALRM)
{
sigaInst.sa_flags = SA_RESTART;
}
sigaInst.sa_handler = handler;
/*
sigset_t sa_mask
This specifies a set of signals to be blocked while the handler runs. Blocking is explained in Blocking for Handler. Note that the signal that was delivered is automatically blocked by default before its handler is started; this is true regardless of the value in sa_mask. If you want that signal not to be blocked within its handler, you must write code in the handler to unblock it.
*/
sigaInst.sa_mask=block_mask;
sigaction(signum, &sigaInst, NULL);
}
static void ctrl_sighandler(int signo)
{
printf("enter signal handler...!\n");
if (signo == SIGTERM)
{
g_bTerminate = 1;
}
}
int main(){
sigset_t mask, oldmask;
sigset_t block_mask;
//The user can use "kill -15 XXX" to terminate the progarm.
register_signal(SIGTERM, ctrl_sighandler);
sigemptyset(&block_mask);
//Block SIGQUIT (Terminal quit (POSIX)). The user can not use "Ctrl+\" to terminate the procgram.
sigaddset(&block_mask,SIGQUIT);
//Block SIGINT (Terminal interrupt (ANSI)). The user can not use "Ctrl+C" to terminate the procgram.
sigaddset(&block_mask, SIGINT);
sigprocmask (SIG_BLOCK, &block_mask, NULL);
/* Set up the mask of signals to temporarily block. */
sigemptyset (&mask);
sigaddset (&mask, SIGTERM);
//daemon(0, 0);
//Wait for SIGTERM arriving...
//1. temporarily block SIGTERM
sigprocmask (SIG_BLOCK, &mask, &oldmask);
while (g_bTerminate == 0)
sigsuspend (&oldmask);//2. SIGTERM is not in oldmask. So when one signal arrivies, sigsuspend() return. And then check g_bTerminate. If the signal is SIGTERM, the g_bTerminate will be set as 1. So the while-loop is break.
sigprocmask (SIG_UNBLOCK, &mask, NULL);//3. Remove SIGTERM from the block list.
printf("main() has been terminated....\n");
return 0;
}
2010年3月26日 星期五
handle的概念
#include stdio.h
#include stdlib.h
#include string.h
#if !defined(__wtypes_h__) && !defined(_SCODE_)
typedef unsigned int SCODE;
#define _SCODE_
#endif
#ifndef HANDLE // h
typedef void * HANDLE;
#endif
#ifndef S_OK
#define S_OK ((SCODE) 0)
#endif
#ifndef S_FAIL
#define S_FAIL ((SCODE) -1)
#endif
#ifndef UCHAR // uc
typedef unsigned char UCHAR;
#endif
SCODE my_malloc(HANDLE *ph,size_t size)
{
void *ptr=(void *)malloc(size);
if(ptr== NULL)
{
return S_FAIL;
}
*ph=ptr;
printf("ptr=%p\n",ptr);
return S_OK;
}
SCODE my_free(HANDLE *ph)
{
void *ptr=(void *)(*ph);
if(ptr != NULL)
{
free(ptr);
}
return S_OK;
}
int main()
{
HANDLE handle=NULL;
char *szMsg=NULL;
if(my_malloc(&handle,sizeof(char)*128)==S_OK)
{
szMsg=(char *)(handle);
strncpy(szMsg,"hello!",strlen("hello!"));
}
printf("szMsg=%p handle=%p\n",szMsg,handle);
printf("szMsg=%s\n",szMsg);
if(handle != NULL)
{
my_free(&handle);
}
return 0;
}
#include stdlib.h
#include string.h
#if !defined(__wtypes_h__) && !defined(_SCODE_)
typedef unsigned int SCODE;
#define _SCODE_
#endif
#ifndef HANDLE // h
typedef void * HANDLE;
#endif
#ifndef S_OK
#define S_OK ((SCODE) 0)
#endif
#ifndef S_FAIL
#define S_FAIL ((SCODE) -1)
#endif
#ifndef UCHAR // uc
typedef unsigned char UCHAR;
#endif
SCODE my_malloc(HANDLE *ph,size_t size)
{
void *ptr=(void *)malloc(size);
if(ptr== NULL)
{
return S_FAIL;
}
*ph=ptr;
printf("ptr=%p\n",ptr);
return S_OK;
}
SCODE my_free(HANDLE *ph)
{
void *ptr=(void *)(*ph);
if(ptr != NULL)
{
free(ptr);
}
return S_OK;
}
int main()
{
HANDLE handle=NULL;
char *szMsg=NULL;
if(my_malloc(&handle,sizeof(char)*128)==S_OK)
{
szMsg=(char *)(handle);
strncpy(szMsg,"hello!",strlen("hello!"));
}
printf("szMsg=%p handle=%p\n",szMsg,handle);
printf("szMsg=%s\n",szMsg);
if(handle != NULL)
{
my_free(&handle);
}
return 0;
}
2010年2月11日 星期四
PHY and MAC (Media Access Control)
PHY:
PHY is a common abbreviation for the physical layer of the OSI model.
A PHY connects a link layer device (often called a MAC (Medium Access Controller)) to a physical medium such as an optical fibre or copper cable. A PHY typically includes a PCS and a PMD layer. The PCS encodes and decodes the data that is transmitted and received. The purpose of the encoding is to make it easier for the receiver to recover the signal.
MAC:
The Media Access Control (MAC) data communication protocol sub-layer, also known as the Medium Access Control, is a sublayer of the Data Link Layer specified in the seven-layer OSI model (layer 2).
It provides addressing and channel access control mechanisms that make it possible for several terminals or network nodes to communicate within a multi-point network, typically a local area network (LAN) or metropolitan area network (MAN).
The hardware that implements the MAC is referred to as a Medium Access Controller.
The MAC sub-layer acts as an interface between the Logical Link Control (LLC) sublayer and the network's physical layer. The MAC layer emulates a full-duplex logical communication channel in a multi-point network. This channel may provide unicast, multicast or broadcast communication service.
IEEE 802 LAN architecture:
Practical, connectionless LANs began with the pre-IEEE Ethernet specification, which is the ancestor of IEEE 802.3. This layer manages the interaction of devices with a shared medium, which is the function of a Media Access Control sublayer. Above this MAC sublayer is the media-independent IEEE 802.2 Logical Link Control (LLC) sublayer, which deals with addressing and multiplexing on multiaccess media.
While IEEE 802.3 is the dominant wired LAN protocol and IEEE 802.11 the wireless LAN protocol, obsolescent MAC layers include Token Ring and FDDI. The MAC sublayer detects but does not correct errors
OSI Model
7 Application Layer
6 Presentation Layer
5 Session Layer
4 Transport Layer
3 Network Layer
2 Data Link Layer
* LLC sublayer
* MAC sublayer
1 Physical Layer
Reference:
http://en.wikipedia.org/wiki/PHY_%28chip%29
http://en.wikipedia.org/wiki/Media_Access_Control
http://en.wikipedia.org/wiki/Logical_Link_Control
http://en.wikipedia.org/wiki/OSI_model
PHY is a common abbreviation for the physical layer of the OSI model.
A PHY connects a link layer device (often called a MAC (Medium Access Controller)) to a physical medium such as an optical fibre or copper cable. A PHY typically includes a PCS and a PMD layer. The PCS encodes and decodes the data that is transmitted and received. The purpose of the encoding is to make it easier for the receiver to recover the signal.
MAC:
The Media Access Control (MAC) data communication protocol sub-layer, also known as the Medium Access Control, is a sublayer of the Data Link Layer specified in the seven-layer OSI model (layer 2).
It provides addressing and channel access control mechanisms that make it possible for several terminals or network nodes to communicate within a multi-point network, typically a local area network (LAN) or metropolitan area network (MAN).
The hardware that implements the MAC is referred to as a Medium Access Controller.
The MAC sub-layer acts as an interface between the Logical Link Control (LLC) sublayer and the network's physical layer. The MAC layer emulates a full-duplex logical communication channel in a multi-point network. This channel may provide unicast, multicast or broadcast communication service.
IEEE 802 LAN architecture:
Practical, connectionless LANs began with the pre-IEEE Ethernet specification, which is the ancestor of IEEE 802.3. This layer manages the interaction of devices with a shared medium, which is the function of a Media Access Control sublayer. Above this MAC sublayer is the media-independent IEEE 802.2 Logical Link Control (LLC) sublayer, which deals with addressing and multiplexing on multiaccess media.
While IEEE 802.3 is the dominant wired LAN protocol and IEEE 802.11 the wireless LAN protocol, obsolescent MAC layers include Token Ring and FDDI. The MAC sublayer detects but does not correct errors
OSI Model
7 Application Layer
6 Presentation Layer
5 Session Layer
4 Transport Layer
3 Network Layer
2 Data Link Layer
* LLC sublayer
* MAC sublayer
1 Physical Layer
Reference:
http://en.wikipedia.org/wiki/PHY_%28chip%29
http://en.wikipedia.org/wiki/Media_Access_Control
http://en.wikipedia.org/wiki/Logical_Link_Control
http://en.wikipedia.org/wiki/OSI_model
2010年2月10日 星期三
Profile and Level in MPEG-4
MPEG-4 provides a large and rich set of tools (http://www.m4if.org/resources/profiles/visualtools.php) for the coding of visual objects. For effective implementation of the standard,subsets of the MPEG-4 tool sets have been provided for use in specific applications.These subsets, called 'Profiles', limit the size of the tool set a decoder is required to implement.In order to restrict computational complexity, one or more 'Levels' are set for each Profile. A Profile@Level combination allows:
. a codec builder to implement only the subset of the standard
he needs, while maintaining interworking with other MPEG-4
devices that implement the same combination, and
. checking whether MPEG-4 devices comply with the standard
('conformance testing').
reference:
http://tools.ietf.org/html/rfc3640#page-31
http://www.m4if.org/resources/profiles/
. a codec builder to implement only the subset of the standard
he needs, while maintaining interworking with other MPEG-4
devices that implement the same combination, and
. checking whether MPEG-4 devices comply with the standard
('conformance testing').
reference:
http://tools.ietf.org/html/rfc3640#page-31
http://www.m4if.org/resources/profiles/
2010年2月9日 星期二
USB type A connector, type B connector, and Hub名詞整理
Type A connector
(1) Found on host controllers and hubs, the A-style connector is a flat, rectangular interface.
(2) You can use it is to plug devices into the CPU or USB hub.
(3) It is as the USB downstream port.
(4)Use it to connect USB devices or another USB hub.
(5) The is picture of the connector:
http://www.allproducts.com/communication/kinsun/14usb-b-l.jpg
Type B connector
(1)It is designed for use on USB peripheral devices. The B-style interface is squarish in shape, and has slightly beveled corners on the top ends of the connector.
(2)It attaches directly to the device (such as a printer or digital camera).
(3)It is as the USB upstream port.
(4)Use it to connect USB devices to your computer or USB hub.
(5) The is picture of the connector:
http://www.allproducts.com/ee/fuyao/Product-200567105039-l.jpg
Downstream is data sent from your computer to the device.
Upsream is from the device to your computer.
USB Hub
This is either built into a device or is a separate unit, which carries a number of downstream USB ports available for peripherals. A hub can also be bus-powered (voltage is drawn from the PC’s bus) or self-powered (voltage is drawn from the mains). In each case an upstream port is linked to the PC.
reference:
http://www.cablestogo.com/resources/usb.asp
http://www.webopedia.com/DidYouKnow/Computer_Science/2005/usb.asp
http://74.125.153.132/search?q=cache:L2-P-DrgiFwJ:support.dell.com/support/edocs/systems/3007wfp/en/about.htm+downstream+usb&cd=3&hl=zh-TW&ct=clnk&gl=tw
http://74.125.153.132/search?q=cache:nfXlfIvxmlIJ:askville.amazon.com/Usb-dummies-explain-USB-downstream-upstream-answers-web/AnswerViewer.do%3FrequestId%3D6690405+downstream+usb&cd=1&hl=zh-TW&ct=clnk&gl=tw
(1) Found on host controllers and hubs, the A-style connector is a flat, rectangular interface.
(2) You can use it is to plug devices into the CPU or USB hub.
(3) It is as the USB downstream port.
(4)Use it to connect USB devices or another USB hub.
(5) The is picture of the connector:
http://www.allproducts.com/communication/kinsun/14usb-b-l.jpg
Type B connector
(1)It is designed for use on USB peripheral devices. The B-style interface is squarish in shape, and has slightly beveled corners on the top ends of the connector.
(2)It attaches directly to the device (such as a printer or digital camera).
(3)It is as the USB upstream port.
(4)Use it to connect USB devices to your computer or USB hub.
(5) The is picture of the connector:
http://www.allproducts.com/ee/fuyao/Product-200567105039-l.jpg
Downstream is data sent from your computer to the device.
Upsream is from the device to your computer.
USB Hub
This is either built into a device or is a separate unit, which carries a number of downstream USB ports available for peripherals. A hub can also be bus-powered (voltage is drawn from the PC’s bus) or self-powered (voltage is drawn from the mains). In each case an upstream port is linked to the PC.
reference:
http://www.cablestogo.com/resources/usb.asp
http://www.webopedia.com/DidYouKnow/Computer_Science/2005/usb.asp
http://74.125.153.132/search?q=cache:L2-P-DrgiFwJ:support.dell.com/support/edocs/systems/3007wfp/en/about.htm+downstream+usb&cd=3&hl=zh-TW&ct=clnk&gl=tw
http://74.125.153.132/search?q=cache:nfXlfIvxmlIJ:askville.amazon.com/Usb-dummies-explain-USB-downstream-upstream-answers-web/AnswerViewer.do%3FrequestId%3D6690405+downstream+usb&cd=1&hl=zh-TW&ct=clnk&gl=tw
2010年2月5日 星期五
align 的用法(u-boot源代码分析)
轉載自:http://blog.chinaunix.net/u3/94328/showart_1917728.html
今决定认真分析一下u-boot的代码,但一开始就被“.balignl 16 0xdeadbeef”这条语句难住了,还好,google了一下,找到了《分析了一下 align 的用法》这篇文章,作者写得很好,看完后,我根据自己的实验结果,做了适当的更改,以让自己看起来更明白,把它记录如下:
.align 就是用来对齐的,究竟怎么对齐,有啥情况?下面分析一下
(一)
$vim align1.s
在新建的文件编辑以下代码:
_start:
b reset
.byte 0x55
.byte 0xaa
reset:
ldr r0, =0x53000000
保存后,执行如下命令:
$arm-linux-as align1.s -o align1.o
这样的话有的编译器可能会报错,但我的编译器没有报错,虽然没有报错,但反汇编的结果显示,运行时肯定会出问题。
执行如下命令:
$arm-linux-objdump -d align1.o
显示如下:
00000000 <_start>:
0: ea000000 b 4 <_start+0x4>
4: 0453aa55 ldreqb s1, [r3], -#2645
00000006:
6: e3a00453 mov r0, #1392508928 ; 0x53000000
很明显,跳转语句应该跳到0x06处,而它却跳到0x04处,我们分析一下。首先,ARM指令都是32位的,这里要求4字节(一个word)对齐,b reset 指令占了4个字节,接着我们用 .byte 指令定义2个常数,因为这里是 byte 类型,所以只占了八位,两个数据,一共占16位。由于连接器内部有一个程序地址计数指针,里面保存着当前的地址,这地址指针是连接器内部工作需要的,我们不需要理会,只需要了解有这么一个机制。假如_start从0x00,第一条指令占4个byte,然后连续分配2个byte,当前地址指针应该是 0x06,那么问题来了,下条指令,也就是标号 reset 处的ldr指令,是一条ARM指令,这要求是 4个字节对齐的,当前的地址为 0x06,并不能满足这个要求,所以编译器自动将地址指针跳到0x04。
解决办法很简单,我们只需要加一条 .align 指令,问题就解决了
_start:
b reset
.byte 0x55
.byte 0xaa
.align
reset:
ldr r0, =0x53000000
编译结果是:
00000000 <_start>:
0: ea000000 b 8
4: 0000aa55 andeq sl, r0, r5, asr sl
00000008:
8: e3a00453 mov r0, #1392508928 ; 0x53000000
在两个 .byte 指令后自动补零,直到满足地址要求为止。这里就是将地址累加到 0x08符合ARM指令要求,所以在这里写入下条指令。这是基本内容,下面研究一下其他
(二).align 5
这里只是一个例子,重点想说的是 这个 .align 5 后面的 5 究竟是什么意思? uboot里面就有这指令。我们继续做做试验,看看编译结果是什么
_start:
b reset
.align 5
.byte 0x55
.align 5
.byte 0xaa
.align
reset:
ldr r0, =0x53000000
编译结果:
00000000 <_start>:
0: ea00000f b 44
...
20: 00000055 andeq r0, r0, r5, asr r0
...
40: 000000aa andeq r0, r0, sl, lsr #1
00000044:
44: e3a00453 mov r0, #1392508928 ; 0x53000000
我们发现这编译结果有点意思,这地址分配一下子上去了,但是也不难,分析一下就OK,看那个 20 和 40 ,这里是十六进制,也就是 32 和 64了。那么很容易可以联想到,这里做的是幂运算,也就是 .align 5 对齐的地址为 2^5 = 32,之前的地址全部补零。
(三).balignl 16,0xdeadbeef
_start:
b reset
.balignl 16,0xdeadbeef
reset:
ldr r0, =0x53000000
在看uboot的时候还有这么一个语句,查了半天as的手册才找到,囧,不过稍微做了一下实现,觉得又不是很难,我们看看结果:
00000000 <_start>:
0: ea000002 b 10
4: deadbeef cdple 14, 10, cr11, cr13, cr15, {7}
8: deadbeef cdple 14, 10, cr11, cr13, cr15, {7}
c: deadbeef cdple 14, 10, cr11, cr13, cr15, {7}
00000010:
10: e3a00453 mov r0, #1392508928 ; 0x53000000
可以看出,这指令就是将 deadbeef字符串填进去,一共填到地址为16对齐的地方为指,上面可以看到,这里填到 0x10 也就是 16了。
今决定认真分析一下u-boot的代码,但一开始就被“.balignl 16 0xdeadbeef”这条语句难住了,还好,google了一下,找到了《分析了一下 align 的用法》这篇文章,作者写得很好,看完后,我根据自己的实验结果,做了适当的更改,以让自己看起来更明白,把它记录如下:
.align 就是用来对齐的,究竟怎么对齐,有啥情况?下面分析一下
(一)
$vim align1.s
在新建的文件编辑以下代码:
_start:
b reset
.byte 0x55
.byte 0xaa
reset:
ldr r0, =0x53000000
保存后,执行如下命令:
$arm-linux-as align1.s -o align1.o
这样的话有的编译器可能会报错,但我的编译器没有报错,虽然没有报错,但反汇编的结果显示,运行时肯定会出问题。
执行如下命令:
$arm-linux-objdump -d align1.o
显示如下:
00000000 <_start>:
0: ea000000 b 4 <_start+0x4>
4: 0453aa55 ldreqb s1, [r3], -#2645
00000006
6: e3a00453 mov r0, #1392508928 ; 0x53000000
很明显,跳转语句应该跳到0x06处,而它却跳到0x04处,我们分析一下。首先,ARM指令都是32位的,这里要求4字节(一个word)对齐,b reset 指令占了4个字节,接着我们用 .byte 指令定义2个常数,因为这里是 byte 类型,所以只占了八位,两个数据,一共占16位。由于连接器内部有一个程序地址计数指针,里面保存着当前的地址,这地址指针是连接器内部工作需要的,我们不需要理会,只需要了解有这么一个机制。假如_start从0x00,第一条指令占4个byte,然后连续分配2个byte,当前地址指针应该是 0x06,那么问题来了,下条指令,也就是标号 reset 处的ldr指令,是一条ARM指令,这要求是 4个字节对齐的,当前的地址为 0x06,并不能满足这个要求,所以编译器自动将地址指针跳到0x04。
解决办法很简单,我们只需要加一条 .align 指令,问题就解决了
_start:
b reset
.byte 0x55
.byte 0xaa
.align
reset:
ldr r0, =0x53000000
编译结果是:
00000000 <_start>:
0: ea000000 b 8
4: 0000aa55 andeq sl, r0, r5, asr sl
00000008
8: e3a00453 mov r0, #1392508928 ; 0x53000000
在两个 .byte 指令后自动补零,直到满足地址要求为止。这里就是将地址累加到 0x08符合ARM指令要求,所以在这里写入下条指令。这是基本内容,下面研究一下其他
(二).align 5
这里只是一个例子,重点想说的是 这个 .align 5 后面的 5 究竟是什么意思? uboot里面就有这指令。我们继续做做试验,看看编译结果是什么
_start:
b reset
.align 5
.byte 0x55
.align 5
.byte 0xaa
.align
reset:
ldr r0, =0x53000000
编译结果:
00000000 <_start>:
0: ea00000f b 44
...
20: 00000055 andeq r0, r0, r5, asr r0
...
40: 000000aa andeq r0, r0, sl, lsr #1
00000044
44: e3a00453 mov r0, #1392508928 ; 0x53000000
我们发现这编译结果有点意思,这地址分配一下子上去了,但是也不难,分析一下就OK,看那个 20 和 40 ,这里是十六进制,也就是 32 和 64了。那么很容易可以联想到,这里做的是幂运算,也就是 .align 5 对齐的地址为 2^5 = 32,之前的地址全部补零。
(三).balignl 16,0xdeadbeef
_start:
b reset
.balignl 16,0xdeadbeef
reset:
ldr r0, =0x53000000
在看uboot的时候还有这么一个语句,查了半天as的手册才找到,囧,不过稍微做了一下实现,觉得又不是很难,我们看看结果:
00000000 <_start>:
0: ea000002 b 10
4: deadbeef cdple 14, 10, cr11, cr13, cr15, {7}
8: deadbeef cdple 14, 10, cr11, cr13, cr15, {7}
c: deadbeef cdple 14, 10, cr11, cr13, cr15, {7}
00000010
10: e3a00453 mov r0, #1392508928 ; 0x53000000
可以看出,这指令就是将 deadbeef字符串填进去,一共填到地址为16对齐的地方为指,上面可以看到,这里填到 0x10 也就是 16了。
2010年1月28日 星期四
Use screen as the UART console
Use screen as the UART console:
screen /dev/ttyUSB0 115200,cs8,-ixon,-ixon,istrip
When do not use the screen, you must kill the related processes:
qustion@jeffOA:~$ ps aux | grep ttyUSB0
qustion 3206 0.0 0.0 4364 992 pts/0 S+ 18:19 0:00 screen /dev/ttyUSB0 115200,cs8,-ixon,-ixon,istrip
qustion 3207 0.0 0.1 4496 1092 ? Ss 18:19 0:00 SCREEN /dev/ttyUSB0 115200,cs8,-ixon,-ixon,istrip
qustion 3233 0.0 0.0 3472 800 pts/1 S+ 18:19 0:00 grep ttyUSB0
qustion@jeffOA:~$ sudo kill -9 3206
qustion@jeffOA:~$ ps aux | grep ttyUSB0
qustion 3207 0.0 0.1 4496 1092 ? Ss 18:19 0:00 SCREEN /dev/ttyUSB0 115200,cs8,-ixon,-ixon,istrip
qustion 3236 0.0 0.0 3472 800 pts/1 R+ 18:20 0:00 grep ttyUSB0
qustion@jeffOA:~$ sudo kill -9 3207
qustion@jeffOA:~$
screen /dev/ttyUSB0 115200,cs8,-ixon,-ixon,istrip
When do not use the screen, you must kill the related processes:
qustion@jeffOA:~$ ps aux | grep ttyUSB0
qustion 3206 0.0 0.0 4364 992 pts/0 S+ 18:19 0:00 screen /dev/ttyUSB0 115200,cs8,-ixon,-ixon,istrip
qustion 3207 0.0 0.1 4496 1092 ? Ss 18:19 0:00 SCREEN /dev/ttyUSB0 115200,cs8,-ixon,-ixon,istrip
qustion 3233 0.0 0.0 3472 800 pts/1 S+ 18:19 0:00 grep ttyUSB0
qustion@jeffOA:~$ sudo kill -9 3206
qustion@jeffOA:~$ ps aux | grep ttyUSB0
qustion 3207 0.0 0.1 4496 1092 ? Ss 18:19 0:00 SCREEN /dev/ttyUSB0 115200,cs8,-ixon,-ixon,istrip
qustion 3236 0.0 0.0 3472 800 pts/1 R+ 18:20 0:00 grep ttyUSB0
qustion@jeffOA:~$ sudo kill -9 3207
qustion@jeffOA:~$
How to write Linux version DNW (a Samsung USB fusing tool)
1. 參考http://chengchungchun.spaces.live.com/blog/cns!EEDBBE1B9C2FFA9D!1484.entry
2. "dnw_linux" 是由二個程式所組成:dnw.c 和 secbulk.c。dnw.c負責製作dnw packet。secbulk.c負責將dnw packet透過usb end point將資料送到target端。
3. cd dnw_linux/dnw;gcc -o dnw dnw.c
4. cd dnw_linux/secbulk;make -C /lib/modules/`uname -r`/build M=`pwd` modules
6. 執行方式
(1) Use Putty to connect the board. Under Uboot keyin the following command:
dnw 32000000
(2) Under the host computer, keyin the following command:
cd dnw_linux/secbulk
sudo insmod ./secbulk.ko
cd dnw_linux/dnw
sudo sudo ./dnw u-boot.bin
7. dnw_linux/dnw/dnw.c:
#include stdio.h
#include stdlib.h
#include malloc.h
#include sys/types.h
#include sys/stat.h
#include unistd.h
#include fcntl.h
const char* dev = "/dev/secbulk0";
int main(int argc, char* argv[])
{
unsigned char* file_buffer = NULL;
if( 2 != argc )
{
printf("Usage: dwn\n");
return 1;
}
int fd = open(argv[1], O_RDONLY);
if(-1 == fd)
{
printf("Can not open file - %s\n", argv[1]);
return 1;
}
struct stat file_stat;
if( -1 == fstat(fd, &file_stat) )
{
printf("Get file size filed!\n");
return 1;
}
file_buffer = (char*)malloc(file_stat.st_size+10);
if(NULL == file_buffer)
{
printf("malloc failed!\n");
goto error;
}
if( file_stat.st_size != read(fd, file_buffer+8, file_stat.st_size))
{
printf("Read file failed!\n");
goto error;
}
printf("file name : %s\n", argv[1]);
printf("file size : %d bytes\n", file_stat.st_size);
int fd_dev = open(dev, O_WRONLY);
if( -1 == fd_dev)
{
printf("Can not open %s\n", dev);
goto error;
}
*((unsigned long*)file_buffer) = 0x32000000; //load address
*((unsigned long*)file_buffer+1) = file_stat.st_size+10; //file size
unsigned short sum = 0;
int i;
for(i=8; i {
sum += file_buffer[i];
}
*((unsigned short*)(file_buffer + file_stat.st_size + 8)) = sum;
printf("Writing data...\n");
size_t remain_size = file_stat.st_size+10;
size_t block_size = 512;//remain_size / 100;
size_t writed = 0;
while(remain_size>0)
{
size_t to_write = remain_size > block_size ? block_size:remain_size;
if( to_write != write(fd_dev, file_buffer+writed, to_write))
{
printf("failed!\n");
return 1;
}
remain_size -= to_write;
writed += to_write;
printf("\r%d%\t %d bytes ", writed*100/(file_stat.st_size+10), writed);
fflush(stdout);
}
printf("OK\n");
return 0;
error:
if(-1!=fd_dev) close(fd_dev);
if(fd != -1) close(fd);
if( NULL!=file_buffer )
free(file_buffer);
return -1;
}
8. dnw_linux/secbulk/secbulk.c:
#include linux/kernel.h
#include linux/module.h
#include linux/usb.h
#include linux/fs.h
#include linux/mutex.h
#include linux/slab.h
#include linux/uaccess.h
#define SECBULK_MAJOR 102
#define SECBULK_MINOR 0
#define DRIVER_NAME "secbulk"
#define BULKOUT_BUFFER_SIZE 512
struct secbulk_dev
{
struct usb_device *udev;
struct mutex io_mutex;
char* bulkout_buffer;
__u8 bulk_out_endpointAddr;
};
static struct usb_class_driver secbulk_class;
//idVendor=04e8, idProduct=1234
static struct usb_device_id secbulk_table[]= {
// { USB_DEVICE(0x5345, 0x1234)},
{ USB_DEVICE(0x04e8, 0x1234)},
{ }
};
static struct usb_driver secbulk_driver;
static void secbulk_disconnect(struct usb_interface *interface)
{
struct secbulk_dev *dev = NULL;
printk(KERN_INFO "secbulk:secbulk disconnected!\n");
dev = usb_get_intfdata(interface);
if( NULL != dev )
kfree(dev);
usb_deregister_dev(interface, &secbulk_class);
return;
}
static ssize_t secbulk_read(struct file *file, char __user *buf, size_t len, loff_t *loff)
{
return -EPERM;
}
static ssize_t secbulk_write(struct file *file, const char __user *buf, size_t len, loff_t *loff)
{
size_t to_write;
struct secbulk_dev *dev = file->private_data;
int ret;
int actual_length;
size_t total_writed;
total_writed = 0;
while(len > 0)
{
to_write = min(len, BULKOUT_BUFFER_SIZE);
if(copy_from_user(dev->bulkout_buffer, buf+total_writed, to_write))
{
printk(KERN_ERR "secbulk:copy_from_user failed!\n");
return -EFAULT;
}
ret = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
dev->bulkout_buffer,
to_write,
&actual_length,
3*HZ);
if(ret || actual_length!=to_write)
{
printk(KERN_ERR "secbulk:usb_bulk_msg failed!\n");
return -EFAULT;
}
len -= to_write;
total_writed += to_write;
}
return total_writed;
}
static int secbulk_open(struct inode *node, struct file *file)
{
struct usb_interface *interface;
struct secbulk_dev *dev;
interface = usb_find_interface(&secbulk_driver, iminor(node));
if(!interface)
return -ENODEV;
dev = usb_get_intfdata(interface);
dev->bulkout_buffer = kzalloc(BULKOUT_BUFFER_SIZE, GFP_KERNEL);
if(!(dev->bulkout_buffer))
return -ENOMEM;
if(!mutex_trylock(&dev->io_mutex))
return -EBUSY;
file->private_data = dev;
return 0;
}
static int secbulk_release(struct inode *node, struct file *file)
{
struct secbulk_dev *dev;
dev = (struct secbulk_dev*)(file->private_data);
kfree(dev->bulkout_buffer);
mutex_unlock(&dev->io_mutex);
return 0;
}
static struct file_operations secbulk_fops = {
.owner = THIS_MODULE,
.read = secbulk_read,
.write = secbulk_write,
.open = secbulk_open,
.release= secbulk_release,
};
static struct usb_class_driver secbulk_class = {
.name = "secbulk%d",
.fops = &secbulk_fops,
.minor_base= 100,
};
static int secbulk_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
int ret;
struct secbulk_dev *dev;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
int i;
printk(KERN_INFO "secbulk:secbulk probing...\n");
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if(!dev)
{
ret = -ENOMEM;
goto error;
}
iface_desc = interface->cur_altsetting;
for(i=0; i < iface_desc->desc.bNumEndpoints; i++)
{
endpoint = &(iface_desc->endpoint[i].desc);
if(!dev->bulk_out_endpointAddr
&& usb_endpoint_is_bulk_out(endpoint))
{
printk(KERN_INFO "secbulk:bulk out endpoint found!\n");
dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
break;
}
}
if(!(dev->bulk_out_endpointAddr))
{
ret = -EBUSY;
goto error;
}
ret = usb_register_dev(interface, &secbulk_class);
if(ret)
{
printk(KERN_ERR "secbulk: usb_register_dev failed!\n");
return ret;
}
dev->udev = usb_get_dev(interface_to_usbdev(interface));
usb_set_intfdata(interface, dev);
mutex_init(&dev->io_mutex);
return 0;
error:
if(!dev)
kfree(dev);
return ret;
}
static struct usb_driver secbulk_driver= {
.name= "secbulk",
.probe= secbulk_probe,
.disconnect= secbulk_disconnect,
.id_table= secbulk_table,
.supports_autosuspend=0,
};
static int __init secbulk_init(void)
{
int result;
printk(KERN_INFO "secbulk:secbulk loaded\n");
result = usb_register(&secbulk_driver);
if(result)
{ printk(KERN_ERR "secbulk:usb_register failed: %d", result);
return result;
}
return 0;
}
static void __exit secbulk_exit(void)
{
usb_deregister(&secbulk_driver);
printk(KERN_INFO "secbulk:secbulk unloaded\n");
}
module_init(secbulk_init);
module_exit(secbulk_exit);
MODULE_LICENSE("GPL");
9.dnw_linux/secbulk/Makefile:
obj-m := secbulk.o
secbulk-m := secbulk.o
2. "dnw_linux" 是由二個程式所組成:dnw.c 和 secbulk.c。dnw.c負責製作dnw packet。secbulk.c負責將dnw packet透過usb end point將資料送到target端。
3. cd dnw_linux/dnw;gcc -o dnw dnw.c
4. cd dnw_linux/secbulk;make -C /lib/modules/`uname -r`/build M=`pwd` modules
6. 執行方式
(1) Use Putty to connect the board. Under Uboot keyin the following command:
dnw 32000000
(2) Under the host computer, keyin the following command:
cd dnw_linux/secbulk
sudo insmod ./secbulk.ko
cd dnw_linux/dnw
sudo sudo ./dnw u-boot.bin
7. dnw_linux/dnw/dnw.c:
#include stdio.h
#include stdlib.h
#include malloc.h
#include sys/types.h
#include sys/stat.h
#include unistd.h
#include fcntl.h
const char* dev = "/dev/secbulk0";
int main(int argc, char* argv[])
{
unsigned char* file_buffer = NULL;
if( 2 != argc )
{
printf("Usage: dwn
return 1;
}
int fd = open(argv[1], O_RDONLY);
if(-1 == fd)
{
printf("Can not open file - %s\n", argv[1]);
return 1;
}
struct stat file_stat;
if( -1 == fstat(fd, &file_stat) )
{
printf("Get file size filed!\n");
return 1;
}
file_buffer = (char*)malloc(file_stat.st_size+10);
if(NULL == file_buffer)
{
printf("malloc failed!\n");
goto error;
}
if( file_stat.st_size != read(fd, file_buffer+8, file_stat.st_size))
{
printf("Read file failed!\n");
goto error;
}
printf("file name : %s\n", argv[1]);
printf("file size : %d bytes\n", file_stat.st_size);
int fd_dev = open(dev, O_WRONLY);
if( -1 == fd_dev)
{
printf("Can not open %s\n", dev);
goto error;
}
*((unsigned long*)file_buffer) = 0x32000000; //load address
*((unsigned long*)file_buffer+1) = file_stat.st_size+10; //file size
unsigned short sum = 0;
int i;
for(i=8; i
sum += file_buffer[i];
}
*((unsigned short*)(file_buffer + file_stat.st_size + 8)) = sum;
printf("Writing data...\n");
size_t remain_size = file_stat.st_size+10;
size_t block_size = 512;//remain_size / 100;
size_t writed = 0;
while(remain_size>0)
{
size_t to_write = remain_size > block_size ? block_size:remain_size;
if( to_write != write(fd_dev, file_buffer+writed, to_write))
{
printf("failed!\n");
return 1;
}
remain_size -= to_write;
writed += to_write;
printf("\r%d%\t %d bytes ", writed*100/(file_stat.st_size+10), writed);
fflush(stdout);
}
printf("OK\n");
return 0;
error:
if(-1!=fd_dev) close(fd_dev);
if(fd != -1) close(fd);
if( NULL!=file_buffer )
free(file_buffer);
return -1;
}
8. dnw_linux/secbulk/secbulk.c:
#include linux/kernel.h
#include linux/module.h
#include linux/usb.h
#include linux/fs.h
#include linux/mutex.h
#include linux/slab.h
#include linux/uaccess.h
#define SECBULK_MAJOR 102
#define SECBULK_MINOR 0
#define DRIVER_NAME "secbulk"
#define BULKOUT_BUFFER_SIZE 512
struct secbulk_dev
{
struct usb_device *udev;
struct mutex io_mutex;
char* bulkout_buffer;
__u8 bulk_out_endpointAddr;
};
static struct usb_class_driver secbulk_class;
//idVendor=04e8, idProduct=1234
static struct usb_device_id secbulk_table[]= {
// { USB_DEVICE(0x5345, 0x1234)},
{ USB_DEVICE(0x04e8, 0x1234)},
{ }
};
static struct usb_driver secbulk_driver;
static void secbulk_disconnect(struct usb_interface *interface)
{
struct secbulk_dev *dev = NULL;
printk(KERN_INFO "secbulk:secbulk disconnected!\n");
dev = usb_get_intfdata(interface);
if( NULL != dev )
kfree(dev);
usb_deregister_dev(interface, &secbulk_class);
return;
}
static ssize_t secbulk_read(struct file *file, char __user *buf, size_t len, loff_t *loff)
{
return -EPERM;
}
static ssize_t secbulk_write(struct file *file, const char __user *buf, size_t len, loff_t *loff)
{
size_t to_write;
struct secbulk_dev *dev = file->private_data;
int ret;
int actual_length;
size_t total_writed;
total_writed = 0;
while(len > 0)
{
to_write = min(len, BULKOUT_BUFFER_SIZE);
if(copy_from_user(dev->bulkout_buffer, buf+total_writed, to_write))
{
printk(KERN_ERR "secbulk:copy_from_user failed!\n");
return -EFAULT;
}
ret = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
dev->bulkout_buffer,
to_write,
&actual_length,
3*HZ);
if(ret || actual_length!=to_write)
{
printk(KERN_ERR "secbulk:usb_bulk_msg failed!\n");
return -EFAULT;
}
len -= to_write;
total_writed += to_write;
}
return total_writed;
}
static int secbulk_open(struct inode *node, struct file *file)
{
struct usb_interface *interface;
struct secbulk_dev *dev;
interface = usb_find_interface(&secbulk_driver, iminor(node));
if(!interface)
return -ENODEV;
dev = usb_get_intfdata(interface);
dev->bulkout_buffer = kzalloc(BULKOUT_BUFFER_SIZE, GFP_KERNEL);
if(!(dev->bulkout_buffer))
return -ENOMEM;
if(!mutex_trylock(&dev->io_mutex))
return -EBUSY;
file->private_data = dev;
return 0;
}
static int secbulk_release(struct inode *node, struct file *file)
{
struct secbulk_dev *dev;
dev = (struct secbulk_dev*)(file->private_data);
kfree(dev->bulkout_buffer);
mutex_unlock(&dev->io_mutex);
return 0;
}
static struct file_operations secbulk_fops = {
.owner = THIS_MODULE,
.read = secbulk_read,
.write = secbulk_write,
.open = secbulk_open,
.release= secbulk_release,
};
static struct usb_class_driver secbulk_class = {
.name = "secbulk%d",
.fops = &secbulk_fops,
.minor_base= 100,
};
static int secbulk_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
int ret;
struct secbulk_dev *dev;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
int i;
printk(KERN_INFO "secbulk:secbulk probing...\n");
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if(!dev)
{
ret = -ENOMEM;
goto error;
}
iface_desc = interface->cur_altsetting;
for(i=0; i < iface_desc->desc.bNumEndpoints; i++)
{
endpoint = &(iface_desc->endpoint[i].desc);
if(!dev->bulk_out_endpointAddr
&& usb_endpoint_is_bulk_out(endpoint))
{
printk(KERN_INFO "secbulk:bulk out endpoint found!\n");
dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
break;
}
}
if(!(dev->bulk_out_endpointAddr))
{
ret = -EBUSY;
goto error;
}
ret = usb_register_dev(interface, &secbulk_class);
if(ret)
{
printk(KERN_ERR "secbulk: usb_register_dev failed!\n");
return ret;
}
dev->udev = usb_get_dev(interface_to_usbdev(interface));
usb_set_intfdata(interface, dev);
mutex_init(&dev->io_mutex);
return 0;
error:
if(!dev)
kfree(dev);
return ret;
}
static struct usb_driver secbulk_driver= {
.name= "secbulk",
.probe= secbulk_probe,
.disconnect= secbulk_disconnect,
.id_table= secbulk_table,
.supports_autosuspend=0,
};
static int __init secbulk_init(void)
{
int result;
printk(KERN_INFO "secbulk:secbulk loaded\n");
result = usb_register(&secbulk_driver);
if(result)
{ printk(KERN_ERR "secbulk:usb_register failed: %d", result);
return result;
}
return 0;
}
static void __exit secbulk_exit(void)
{
usb_deregister(&secbulk_driver);
printk(KERN_INFO "secbulk:secbulk unloaded\n");
}
module_init(secbulk_init);
module_exit(secbulk_exit);
MODULE_LICENSE("GPL");
9.dnw_linux/secbulk/Makefile:
obj-m := secbulk.o
secbulk-m := secbulk.o
2010年1月20日 星期三
分析變數宣告在ELF所在的sections
分析變數宣告在ELF所在的sections
1. static 變數a 在assemble階段會allocates storage in the .bss section給該變數
2. global 變數b是Common symbol, 在linking階段才會allocates storage給該變數(The linker merges two or more common symbol declarations for the same symbol.)
3. const global變數c在assemble階段會allocates storage in the .rodata section給該變數
4. local static變數sum 在assemble階段會allocates storage in the .bss section給該變數
1.
//elf_sections_test.c
static int a;
int b;
const int c=9;
int func(int d){
int j=d;
int i=0;
static int sum;
sum+=j;
return sum;
}
2. /usr/local/arm/4.2.2-eabi/usr/bin/arm-unknown-linux-gnueabi-gcc -fomit-frame-pointer -c elf_sections_test.c
3. /usr/local/arm/4.2.2-eabi/usr/bin/arm-unknown-linux-gnueabi-nm elf_sections_test.o
00000004 b a
00000004 C b
00000000 R c
00000000 T func
00000000 b sum.1537
4./usr/local/arm/4.2.2-eabi/usr/bin/arm-unknown-linux-gnueabi-objdump -t elf_sections_test.o | less
elf_sections_test.o: file format elf32-littlearm
SYMBOL TABLE:
00000000 l df *ABS* 00000000 tmp.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .rodata 00000000 .rodata
00000000 l O .bss 00000004 sum.1537
00000004 l O .bss 00000004 a
00000000 l d .comment 00000000 .comment
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 g O .rodata 00000004 c
00000000 g F .text 00000048 func
00000004 O *COM* 00000004 b
5./usr/local/arm/4.2.2-eabi/usr/bin/arm-unknown-linux-gnueabi-objdump -S elf_sections_test.o | less
elf_sections_test.o: file format elf32-littlearm
Disassembly of section .text:
00000000:
0: e24dd010 sub sp, sp, #16 ; 0x10
4: e58d0004 str r0, [sp, #4]
8: e59d3004 ldr r3, [sp, #4]
c: e58d3008 str r3, [sp, #8]
10: e3a03000 mov r3, #0 ; 0x0
14: e58d300c str r3, [sp, #12]
18: e59f3024 ldr r3, [pc, #36] ; 44
1c: e5932000 ldr r2, [r3]
20: e59d3008 ldr r3, [sp, #8]
24: e0822003 add r2, r2, r3
28: e59f3014 ldr r3, [pc, #20] ; 44
2c: e5832000 str r2, [r3]
30: e59f300c ldr r3, [pc, #12] ; 44
34: e5933000 ldr r3, [r3]
38: e1a00003 mov r0, r3
3c: e28dd010 add sp, sp, #16 ; 0x10
40: e12fff1e bx lr
44: 00000000 .word 0x00000000
6.
There are three kinds of global symbols, illustrated here by C examples:
int i = 1;
A definition, which goes in the initialized data section of the output file.
extern int i;
An undefined reference, which does not allocate space. There must be either a definition or a common symbol for the variable somewhere.
int i;
A common symbol. If there are only (one or more) common symbols for a variable, it goes in the uninitialized data area of the output file. The linker merges multiple common symbols for the same variable into a single symbol. If they are of different sizes, it picks the largest size. The linker turns a common symbol into a declaration, if there is a definition of the same variable.
Reference:
http://sourceware.org/binutils/docs-2.16/ld/Options.html#Options
http://www.gursey.gov.tr/Gilgamesh-WWW/IntelCompDocs/ref/decl_com.htm
http://www.math.utah.edu/docs/info/ld_3.html#SEC15
1. static 變數a 在assemble階段會allocates storage in the .bss section給該變數
2. global 變數b是Common symbol, 在linking階段才會allocates storage給該變數(The linker merges two or more common symbol declarations for the same symbol.)
3. const global變數c在assemble階段會allocates storage in the .rodata section給該變數
4. local static變數sum 在assemble階段會allocates storage in the .bss section給該變數
1.
//elf_sections_test.c
static int a;
int b;
const int c=9;
int func(int d){
int j=d;
int i=0;
static int sum;
sum+=j;
return sum;
}
2. /usr/local/arm/4.2.2-eabi/usr/bin/arm-unknown-linux-gnueabi-gcc -fomit-frame-pointer -c elf_sections_test.c
3. /usr/local/arm/4.2.2-eabi/usr/bin/arm-unknown-linux-gnueabi-nm elf_sections_test.o
00000004 b a
00000004 C b
00000000 R c
00000000 T func
00000000 b sum.1537
4./usr/local/arm/4.2.2-eabi/usr/bin/arm-unknown-linux-gnueabi-objdump -t elf_sections_test.o | less
elf_sections_test.o: file format elf32-littlearm
SYMBOL TABLE:
00000000 l df *ABS* 00000000 tmp.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .rodata 00000000 .rodata
00000000 l O .bss 00000004 sum.1537
00000004 l O .bss 00000004 a
00000000 l d .comment 00000000 .comment
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 g O .rodata 00000004 c
00000000 g F .text 00000048 func
00000004 O *COM* 00000004 b
5./usr/local/arm/4.2.2-eabi/usr/bin/arm-unknown-linux-gnueabi-objdump -S elf_sections_test.o | less
elf_sections_test.o: file format elf32-littlearm
Disassembly of section .text:
00000000
0: e24dd010 sub sp, sp, #16 ; 0x10
4: e58d0004 str r0, [sp, #4]
8: e59d3004 ldr r3, [sp, #4]
c: e58d3008 str r3, [sp, #8]
10: e3a03000 mov r3, #0 ; 0x0
14: e58d300c str r3, [sp, #12]
18: e59f3024 ldr r3, [pc, #36] ; 44
1c: e5932000 ldr r2, [r3]
20: e59d3008 ldr r3, [sp, #8]
24: e0822003 add r2, r2, r3
28: e59f3014 ldr r3, [pc, #20] ; 44
2c: e5832000 str r2, [r3]
30: e59f300c ldr r3, [pc, #12] ; 44
34: e5933000 ldr r3, [r3]
38: e1a00003 mov r0, r3
3c: e28dd010 add sp, sp, #16 ; 0x10
40: e12fff1e bx lr
44: 00000000 .word 0x00000000
6.
There are three kinds of global symbols, illustrated here by C examples:
int i = 1;
A definition, which goes in the initialized data section of the output file.
extern int i;
An undefined reference, which does not allocate space. There must be either a definition or a common symbol for the variable somewhere.
int i;
A common symbol. If there are only (one or more) common symbols for a variable, it goes in the uninitialized data area of the output file. The linker merges multiple common symbols for the same variable into a single symbol. If they are of different sizes, it picks the largest size. The linker turns a common symbol into a declaration, if there is a definition of the same variable.
Reference:
http://sourceware.org/binutils/docs-2.16/ld/Options.html#Options
http://www.gursey.gov.tr/Gilgamesh-WWW/IntelCompDocs/ref/decl_com.htm
http://www.math.utah.edu/docs/info/ld_3.html#SEC15
2010年1月11日 星期一
How to write second boot code?
http://tree.celinuxforum.org/CelfPubWiki/FlashRecoveryUtility
http://tree.celinuxforum.org/CelfPubWiki/FlashRecoveryUtility?action=AttachFile&do=view&target=omapfl-1.0.tar.gz
http://tree.celinuxforum.org/CelfPubWiki/FlashRecoveryUtility?action=AttachFile&do=view&target=omapfl-1.0.tar.gz
2010年1月6日 星期三
How to create proc file under Linux kernel modules
Refer to:
1. "The Linux Kernel Module Programming Guide chapter 5." http://tldp.org/LDP/lkmpg/2.6/html/
2. About undeclaring "proc_root" issue http://www.digitalruin.net/node/43
3. When using "current"(a pointer to a structure which includes information on the currently running process) in the kernel module code, we must include the "linux/sched.h".
1. "The Linux Kernel Module Programming Guide chapter 5." http://tldp.org/LDP/lkmpg/2.6/html/
2. About undeclaring "proc_root" issue http://www.digitalruin.net/node/43
3. When using "current"(a pointer to a structure which includes information on the currently running process) in the kernel module code, we must include the "linux/sched.h".
2009年12月23日 星期三
How to read one line from one file as command to execute
//test.sh
#/bin/sh
cat cmdlist.txt | \
while read cmd; do
echo $cmd
sh -c "$cmd"
done
//cmdlist.txt
touch jeff.txt
echo "Hellodefefefe" > jeff.txt
touch hello.txt
#/bin/sh
cat cmdlist.txt | \
while read cmd; do
echo $cmd
sh -c "$cmd"
done
//cmdlist.txt
touch jeff.txt
echo "Hellodefefefe" > jeff.txt
touch hello.txt
2009年12月16日 星期三
selection sort
inline void swap(int *a,int *b ){
*a=*a+*b;
*b=*a-*b;
*a=*a-*b;
return;
}
/*
Selection Sort Algorithm
Selection sort is a simplicity sorting algorithm. It works as its name as it is. Here are basic steps of selection sort algorithm:
1. Find the minimum element in the list
2. Swap it with the element in the first position of the list
3. Repeat the steps above for all remainder elements of the list starting at the second position.
*/
inline void select_sort(int a[], int n){
int i=0,j=0;
int min=0;
for(i=0;i < n-1 ;i++){
min=i;
for(j=i+1;j < n ;j++)
if(a[min] > a[j])
swap(&a[min],&a[j]);
}
}
reference:
http://cprogramminglanguage.net/selection-sort-algorithm-c-souce-code.aspx
*a=*a+*b;
*b=*a-*b;
*a=*a-*b;
return;
}
/*
Selection Sort Algorithm
Selection sort is a simplicity sorting algorithm. It works as its name as it is. Here are basic steps of selection sort algorithm:
1. Find the minimum element in the list
2. Swap it with the element in the first position of the list
3. Repeat the steps above for all remainder elements of the list starting at the second position.
*/
inline void select_sort(int a[], int n){
int i=0,j=0;
int min=0;
for(i=0;i < n-1 ;i++){
min=i;
for(j=i+1;j < n ;j++)
if(a[min] > a[j])
swap(&a[min],&a[j]);
}
}
reference:
http://cprogramminglanguage.net/selection-sort-algorithm-c-souce-code.aspx
binary search
inline int binarysearch(int a[], int n, int key){
int high=n-1;
int low=0;
int mid;
int index=-1;
if(key==a[high] )
return high;
if(key==a[low])
return low;
while((high!=(n-1) )&& (low !=0)){
mid=(low+high)/2;
if(a[mid]==key){
index=mid;
goto found;
}else if(a[mid] < key){
high=n-1;
low=mid+1;
}else if(a[mid] > key){
high=mid-1;
low=0;
}
}
found:
return index;
}
referenc:
http://program-lover.blogspot.com/2008/08/binary-search.html
int high=n-1;
int low=0;
int mid;
int index=-1;
if(key==a[high] )
return high;
if(key==a[low])
return low;
while((high!=(n-1) )&& (low !=0)){
mid=(low+high)/2;
if(a[mid]==key){
index=mid;
goto found;
}else if(a[mid] < key){
high=n-1;
low=mid+1;
}else if(a[mid] > key){
high=mid-1;
low=0;
}
}
found:
return index;
}
referenc:
http://program-lover.blogspot.com/2008/08/binary-search.html
2009年12月15日 星期二
Swap function
With tmp varible:
inline void swap(int *a,int *b ){
int tmp=0;
tmp=*a;
*a=*b;
*b=tmp;
return;
}
Without tmp varible:
inline void swap(int *a,int *b ){
*a=*a+*b;
*b=*a-*b;
*a=*a-*b;
return;
}
reference:
http://www.velocityreviews.com/forums/t283891-swap-two-integers-without-using-a-tmp-variable.html
inline void swap(int *a,int *b ){
int tmp=0;
tmp=*a;
*a=*b;
*b=tmp;
return;
}
Without tmp varible:
inline void swap(int *a,int *b ){
*a=*a+*b;
*b=*a-*b;
*a=*a-*b;
return;
}
reference:
http://www.velocityreviews.com/forums/t283891-swap-two-integers-without-using-a-tmp-variable.html
Structure Arrangement
code:
struct ABC {
int index;
char name[6];
int score;
};
struct DEF{
int att;
char name[3];
};
int main(void)
{
printf("sizeof(ABC) = %d\n", sizeof(struct ABC));
printf("sizeof(DEF) = %d\n", sizeof(struct DEF));
return 0;
}
output:
sizeof(ABC) = 16
sizeof(DEF) = 8
code:
struct ABC {
int index;
char name[6];
int score;
} __attribute__((packed));
struct DEF{
int att;
char name[3];
} __attribute__((packed));
int main(void)
{
printf("sizeof(ABC) = %d\n", sizeof(struct ABC));
printf("sizeof(DEF) = %d\n", sizeof(struct DEF));
return 0;
}
output:
sizeof(ABC) = 14
sizeof(DEF) = 7
A keyword "__attribute__((packed))" that removes all padding.
However, packed structures are slow and inefficient to access. The compiler emulates
unaligned load and store operations by using several aligned accesses with data operations
to merge the results. Only use the __packed keyword where space is far more important
than speed and you can’t reduce padding by rearragement.
struct ABC {
int index;
char name[6];
int score;
};
struct DEF{
int att;
char name[3];
};
int main(void)
{
printf("sizeof(ABC) = %d\n", sizeof(struct ABC));
printf("sizeof(DEF) = %d\n", sizeof(struct DEF));
return 0;
}
output:
sizeof(ABC) = 16
sizeof(DEF) = 8
code:
struct ABC {
int index;
char name[6];
int score;
} __attribute__((packed));
struct DEF{
int att;
char name[3];
} __attribute__((packed));
int main(void)
{
printf("sizeof(ABC) = %d\n", sizeof(struct ABC));
printf("sizeof(DEF) = %d\n", sizeof(struct DEF));
return 0;
}
output:
sizeof(ABC) = 14
sizeof(DEF) = 7
A keyword "__attribute__((packed))" that removes all padding.
However, packed structures are slow and inefficient to access. The compiler emulates
unaligned load and store operations by using several aligned accesses with data operations
to merge the results. Only use the __packed keyword where space is far more important
than speed and you can’t reduce padding by rearragement.
訂閱:
文章 (Atom)