2007年5月6日 星期日

如何在child process 中利用gdb debug

問題描述:
跑一個process, 中間 fork ㄧ個 child process, 之後parent process 繼續執行, 發現child process 好像卡住, 不會繼續動作

Step1.
ulimit -c unlimited
設定 core dump file size 為unlimited, 預設值為0 size

ulimit 程式的主要目的是用來設定程式執行的許多參數, 包括 core file size, data segment size 還有許多其他的參數, 請利用 ulimit -a 來秀所有support 的參數
# ulimit -a
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
pending signals (-i) 1024
max locked memory (kbytes, -l) 32
max memory size (kbytes, -m) unlimited
open files (-n) 1024t
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 3072
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited


Step2.
執行主程式, 可以看到parent process fork 出child process 的process id 為 31887 (利用 getpid()得知), 另外在 ps 也可以看到

# ps aux | grep prog
root 31886 0.1 0.4 2932 904 pts/1 S+ 00:42 0:00 ./prog
root 31887 0.0 0.4 2912 872 pts/1 S+ 00:42 0:00 ./prog
root 31888 0.0 0.4 2928 928 pts/1 S+ 00:42 0:00 ./prog


Step3.
kill -11 31887
送出 SIGSEGV signal 給 child process, child process 收到 segmentation fault 的signal, 就會 core dump 並且在同一個目錄下, 產生core.XXX (XXX為process id) 的檔案, 以這裡的例子而言就是
core.31887

/usr/include/asm/signal.h 下的定義
#define SIGSEGV 11


Step4.
利用 gdb 來debug
# gdb prog core.31887

[略]
Core was generated by `./prog'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /usr/lib/libstdc++.so.6...done.
Loaded symbols for /usr/lib/libstdc++.so.6
Reading symbols from /lib/tls/libm.so.6...done.
Loaded symbols for /lib/tls/libm.so.6
Reading symbols from /lib/libgcc_s.so.1...done.
Loaded symbols for /lib/libgcc_s.so.1
Reading symbols from /lib/tls/libc.so.6...done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
#0 0x0092e7a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
(gdb) bt << 下bt (backtrace) 去 trace 所有的 function
#0 0x0092e7a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1 0x00a0cfc1 in recvfrom () from /lib/tls/libc.so.6
#2 0x0804f0b7 in getMessage (fd=2048, buf=0xfef6d4a0 "\001\001", len=0xfef6cfc4, srcIp=0x800, srcPort=0x800,
verbose=false) at udp.cxx:127
#3 0x0804daf6 in MyTest (myFd=3, dest=@0x800, testNum=1, verbose=false, reply=0xfef6df18) at stun.cxx:2188
#4 0x0804a460 in get_mess (req=0xfef6df50, reqtype=QT_Reflexive, reply=0x0, type=0xfffffe00)
at myclient.cxx:632
#5 0x0804a8c6 in refresh (reqfd=3, svr=0xfef6ea60) at myclient.cxx:572
#6 0x08049299 in main (argc=1, argv=0xfef6eb24) at sip8test.c:71

因為 frame 0, 1 都是system call
frame 2, 3, 4, 5, 6 都是我們程式自己寫的 function
所以可以懷疑程式是卡在 fram 2 getMessage function 當中, 也就是 udp.cxx 的第127 行

Step5.
frame 就是有許多不同層 stack 的意思, 在gdb 中可以利用frame 去jump 到某ㄧ個特定的stack (frame), 來print variable value

(gdb) frame 2 << 我們這裡執行 frame 2 來看stack2 的variable value, 可以用 p XXX 來看
#2 0x0804f0b7 in getMessage (fd=2048, buf=0xfef6d4a0 "\001\001", len=0xfef6cfc4, srcIp=0x800, srcPort=0x800,
verbose=false) at udp.cxx:127
127 *len = recvfrom(fd,


Step6.
這時可以list 來看 code 的內容, 找出錯誤的原因

(gdb) list
122 assert( originalSize > 0 );
123
124 struct sockaddr_in from;
125 int fromLen = sizeof(from);
126
127 *len = recvfrom(fd,
128 buf,
129 originalSize,
130 0,
131 (struct sockaddr *)&from,


Embedded system debug
# toolChain_gdb daemon coreFile
For example
# /opt/v6_be_uclibc/bin/arm_v6_be_uclibc-gdb daemon coreFile

2007年5月3日 星期四

p2p working group and research

Internet2 Peer to Peer Working Group - P2P WG

- [ 翻譯此頁 ]
The Internet2 End-to-End Performance Initiative (E2Epi) is aimed at improving end-to-end performance in the network infrastructure by focusing resources and efforts on improving performance problem detection and resolution throughout ...
p2p.internet2.edu/ - 17k - 頁庫存檔 - 類似網頁

OpenP2P.com -- How the Peer-to-Peer Working Group Ought to Be ...

- [ 翻譯此頁 ]
Tim O'Reilly says that Intel squandered the opportunity to kick off a real working group process at its first meeting of the Peer-to-Peer working group.
www.openp2p.com/pub/a/p2p/2000/10/13/working_grp.html - 29k - 頁庫存檔 - 類似網頁

P2P Networks

- [ 翻譯此頁 ]OpenP2P.com -- p2p development, open source development The O'Reilly Network's P2P DevCenter offers comprehensive P2P developer information. Peer-to-Peer Working Group - Home · Thoughts on Peer-to-Peer.
ntrg.cs.tcd.ie/undergrad/4ba2.02-03/Intro.html - 6k -頁庫存檔 - 類似網頁



pureftp 操作經驗

How to add a user to the pureftp

1. vi /etc/pureftpd.passwd,
新增ㄧ筆user data 在pureftpd 密碼檔當中, ㄧ般標準程序是利用
pure-pw useradd 來新增user, 這裡直接去修改 pureftpd 密碼檔比較快,
直接複製既有其他的user password, 修改username, 以及login 的directory,
david:$2a$07$zSvK1qKH4q3hWAz.E3CAEussQp29Qt/tm2vnEy:10003:100:David Lee:/home/david/./::::::::::::

/home/david/. ==> login directory 之後有一點(.)表示, login 後被 change 為只能看到login directory 以下的檔案, 不能看到整個系統的檔案

2. 新增user 之後, 再去更改該 user 的 password
pure-pw passwd david

3. 最後跑 pure-pw mkdb 即可

2007年5月2日 星期三

shared memory 心得

1. 每個process 都擁有自己的4G virtual memory, 而實際對應到真正的 physically memory, 則是靠kernel 的 Memory management unit 來做處理, 所以在不同的process 之間所看到的同樣位址(virtual address), 實際對應到memory 的 physical address (linear address) 並不相同

2. 如果是 shared memory 則在不同的 process 所看到的 shared memory virtual address 則會對應到同一個physical address

destroy_conntrack 的call 法

destroy_conntrack 的call 法如下
net/ipv4/netfilter/ip_conntrack_core.c
inline void
ip_conntrack_put(struct ip_conntrack *ct)
{
IP_NF_ASSERT(ct);
nf_conntrack_put(&ct->ct_general);
}
include/linux/skbuff.h
static inline void nf_conntrack_put(struct nf_conntrack *nfct)
{
if (nfct && atomic_dec_and_test(&nfct->use))
nfct->destroy(nfct);
}
因為在 init_conntrack 時, 有做 use 的atomic set 動作, 所以必須call ip_conntrack_put 來
作 decrease use 的動作
net/ipv4/netfilter/ip_conntrack_core.c
init_conntrack(const struct ip_conntrack_tuple *tuple,
struct ip_conntrack_protocol *protocol,
struct sk_buff *skb) {
..
[略]
atomic_set(&conntrack->ct_general.use, 1);
conntrack->ct_general.destroy = destroy_conntrack;

2007年5月1日 星期二

shared memory

顯示系統目前的 shared memory
# ipcs -m

------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x0000162e 65536 root 666 27 0
0x00000000 98305 root 666 192 0
0x00001234 163843 root 666 192 0

刪除某ㄧ個特定的 shared memory key

# ipcrm -M 0x0000162e

原先的 shared memory 0x0000162e 已經被刪除了
# ipcs -m

------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 98305 root 666 192 0
0x00001234 163843 root 666 192 0

如何傳遞陣列指標(function variable) 在函數中

#include
#include
#include

struct abc {
int val;
char str[10];
};

void allocatemem(void*** a1) {
int amount;

printf("s1 - &a1: %10p, a1: %10p, *a1: %10p\n", a1, *a1, **a1);
amount = sizeof(struct abc)*16;
if ((*a1=(void**)malloc(amount))==NULL) {
printf("errno: %s, desc: %s\n", errno, strerror(errno));
}
printf("s2 - &a1: %10p, a1: %10p, *a1: %10p\n", a1, *a1, **a1);

memset(*a1, 0, amount);
//printf("memset ok\n");
printf("s4 - &a1: %10p, a1: %10p, *a1: %10p\n", a1, *a1, **a1);
}


void filldata(struct abc (*aa)[16]) {
printf("s6 - &aa: %10p, aa: %10p, *aa: %10p, &(*aa)[0]: %10p, &(*aa)[1]: %10p\n", &aa, aa, *aa, &(*aa)[0], &(*aa)[1]);
(*aa)[0].val = 0;
strcpy((*aa)[0].str, "hello0");
printf("aa[0] ok\n");

(*aa[1]).val = 1;
strcpy((*aa[1]).str, "hello1");
printf("aa[1] ok\n");
}

int main(int argc, char** argv) {
struct abc (*a1)[16];
printf("s0 - &a1: %10p, a1: %10p, *a1: %10p, &(*a1)[0]: %10p, &(*a1)[1]: %10p\n", &a1, a1, *a1, &(*a1)[0], &(*a1)[1]);
allocatemem((void***)&a1);
printf("s5 - &a1: %10p, a1: %10p, *a1: %10p, &(*a1)[0]: %10p, &(*a1)[1]: %10p\n", &a1, a1, *a1, &(*a1)[0], &(*a1)[1]);
filldata(a1);

return 0;
}

# gcc -o a5 ./array5.c

# ./a5
s0 - &a1: 0xfeee4444, a1: 0x943c80, *a1: 0x943c80, &(*a1)[0]: 0x943c80, &(*a1)[1]: 0x943c90
s1 - &a1: 0xfeee4444, a1: 0x943c80, *a1: (nil)
s2 - &a1: 0xfeee4444, a1: 0x8820008, *a1: (nil)
s4 - &a1: 0xfeee4444, a1: 0x8820008, *a1: (nil)
s5 - &a1: 0xfeee4444, a1: 0x8820008, *a1: 0x8820008, &(*a1)[0]: 0x8820008, &(*a1)[1]: 0x8820018
s6 - &aa: 0xfeee4420, aa: 0x8820008, *aa: 0x8820008, &(*aa)[0]: 0x8820008, &(*aa)[1]: 0x8820018
aa[0] ok
aa[1] ok