pstack工具对指定PID的进程输出函数调用栈。
例子:
服务器端程序:server.c
#include <string.h> #include <stdlib.h> #include <stdio.h> #include <sys/socket.h> #include <netdb.h> #include <pthread.h> #include <unistd.h> #include <arpa/inet.h> #include "practical.h" pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //定义一个静态锁 char *message_src; //当前收到来自客户端的源信息 int currentID = 6; char* clientlist[5]; //用户组姓名 void* ThreadMain(void* arg); //挂send void* ThreadMain2(void* arg); //挂阻塞rcvd typedef struct ThreadArgs{ int clientSock; //线程要处理的连接 int nameID; //用户在用户组的位置 }threadMessage; int main(int argc, char* argv[]) { if(argc != 2) { DieWithUserMessage("Parameter(s)", "<Server Port/Service>"); } char* servPort = argv[1]; //First Arg: Local Port message_src = (char*)malloc(120); memset(message_src, 0, 120); int servSock = SetupTCPServerSocket(servPort); if(servSock < 0) { DieWithUserMessage("SetupTCPServerSocker() failed!", "Unable to establish!"); } for(;;) //一直运行 { int clientSock = AcceptTCPConnection(servSock); threadMessage *threadArgs = (threadMessage*)malloc(sizeof(threadMessage)); if(threadArgs == NULL) { DieWithSystemMessage("Malloc() failed!\n"); } threadArgs->clientSock = clientSock; pthread_t threadID; int returnValue = pthread_create(&threadID, NULL, ThreadMain, threadArgs); if(returnValue != 0) { DieWithUserMessage("pThread_Create() failed!", strerror(returnValue)); } //printf("With thread:%ld\n", (long int)threadID); } free(message_src); close(servSock); return 0; } void* ThreadMain(void* threadArgs) { char* sname = (char*)malloc(20); char rongname[] = "The Name Existed"; char rightname[] = "Land Success"; int i = 0; memset(sname, 0, 20); pthread_detach(pthread_self()); int clientSock = ((threadMessage*)threadArgs)->clientSock; while(i != 5) //判断用户名是否存在 { ssize_t nameRcvd = recv(clientSock, sname, 20, 0); if(nameRcvd <= 0) { DieWithSystemMessage("Revc() failed!"); } *(sname + nameRcvd) = '\0'; for(i = 0; i < 5; i++) { if(clientlist[i] != NULL) { if(strcmp(sname, clientlist[i]) == 0) { if(send(clientSock, rongname, sizeof(rongname), 0) <= 0) { DieWithSystemMessage("SendName() failed!\n"); } printf("用户名已经存在!\n"); break; } } } } for(i = 0; i < 5; i++) { if(clientlist[i] == NULL) break; } if(send(clientSock, rightname, sizeof(rightname), 0) <= 0) { DieWithSystemMessage("SendRightNmae() failed!\n"); } printf("接入用户名:%s\n", sname); clientlist[i] = (char*)malloc(20); memset(clientlist[i], 0, 20); strcpy(clientlist[i], sname); //将该连接相关信息传给该连接的第二个线程 ((threadMessage*)threadArgs)->nameID = i; pthread_t threadID; int returnValue = pthread_create(&threadID, NULL, ThreadMain2, threadArgs); if(returnValue != 0) { DieWithUserMessage("pthread_create() failed!", strerror(returnValue)); } while(1) { if(clientlist[i] == NULL) break; if(i == currentID) //判断是否给本连接的信息,是就发送出去 { ssize_t numByteSent = send(clientSock, message_src, 120, 0); if(numByteSent < 0) { DieWithSystemMessage("Send() failed!"); } else if(numByteSent != 120) { DieWithUserMessage("send()", "sent unexpected number of bytes"); } //strcpy(message_src, "null"); currentID = 6; //设置标志,防止在此发送 if(pthread_mutex_unlock(&mutex) != 0) //转发完成就解锁 { printf("unlock failed!\n"); } } } free(sname); close(clientSock); return (NULL); } void* ThreadMain2(void* threadArgs) { char* buffer = (char*)malloc(120); memset(buffer, 0, 120); char* y; char* b; int nameid, j; pthread_detach(pthread_self()); int clientSock = ((threadMessage*)threadArgs)->clientSock; nameid = ((threadMessage*)threadArgs)->nameID; free(threadArgs); while(1) { ssize_t numByteRcvd; int totalRecv = 0; //getchar(); while(totalRecv < 120) { numByteRcvd = recv(clientSock, buffer + totalRecv, 120 - totalRecv, 0); if(numByteRcvd == 0) break; //判断客户关闭 if(numByteRcvd < 0) { DieWithSystemMessage("recv() failed!"); } totalRecv += numByteRcvd; } if(numByteRcvd == 0) break; printf("收到:%s\n", buffer); if(pthread_mutex_lock(&mutex) != 0) printf("Lock Failed!\n"); if(strcmp(buffer, "list") == 0) //编写list命令 { char locate[3] = {"\n1:"}; strcpy(message_src, "服务器在线用户列表:"); for(j = 0; j < 5; j++) { if(clientlist[j] != NULL) { strcat(message_src, locate); strcat(message_src, clientlist[j]); locate[1]++; } } currentID = nameid; continue; } //解析收到的信息,并编码要传递的信息 b = buffer; y = strsep(&b, ":"); for(j = 0; j < 5; j++) { if(clientlist[j] != NULL) if(strcmp(y, clientlist[j]) == 0) break; } if(j == 5) { currentID = nameid; strcpy(message_src, "您要对话的用户不存在!"); } else //加入发送者名字 { currentID = j; strcpy(message_src, clientlist[nameid]); strcat(message_src, ":"); strcat(message_src, b); printf("to: %s\n", message_src); } } printf("用户%s已经退出\n", clientlist[nameid]); free(clientlist[nameid]); clientlist[nameid] = NULL; free(buffer); return (NULL); }
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <pthread.h> #include "practical.h" void* ThreadMain(void* arg); //用来挂阻塞的rcvd struct ThreadArgs { int clientSock; //传递给线程要处理的套接字 }; int main(int argc, char* argv[]) { if(argc != 3) { DieWithUserMessage("Parameter(s)", "<Server Address/Name> [<Server Port/Service>]"); } char* server = argv[1]; //First arg: server address/name char* echoString = (char*)malloc(120); char* service = argv[2]; int sock = SetupTCPClientSocket(server, service); //创建套接字并连接 if(sock < 0) { DieWithUserMessage("SetupTCPClientSocket() failed", "Unable to connect"); } nameland(sock); struct ThreadArgs *threadArgs = (struct ThreadArgs*)malloc(sizeof(struct ThreadArgs)); if(threadArgs == NULL) { DieWithSystemMessage("Malloc() failed"); } threadArgs->clientSock = sock; pthread_t threadID; //创建线程 int returnValue = pthread_create(&threadID, NULL, ThreadMain, threadArgs); if(returnValue != 0) { DieWithUserMessage("pthread_create failed", strerror(returnValue)); } printf("|-------登陆成功请按此格式聊天(用户名:信息内容)---------|\n|--------(信息最长100字符/使用list命令获取在线用户列表/close命令退出)-------|\n"); //挂send for(;;) { scanf("%s", echoString); if(strcmp(echoString, "close") == 0) break; ssize_t numBytes = send(sock, echoString, 120, 0); if(numBytes < 0) { DieWithSystemMessage("send() failed"); } else if(numBytes != 120) { DieWithUserMessage("Send()", "sent unexpected number of bytes"); } printf("发送字节数:%d\n", numBytes); } fputs("欢迎再次使用\n", stdout); free(echoString); close(sock); exit(0); } void *ThreadMain(void* threadArgs) //挂recv { char buffer[120]; //I/O buffer pthread_detach(pthread_self()); int csock = ((struct ThreadArgs*)threadArgs)->clientSock; free(threadArgs); while(1) { int totalRecv = 0; while(totalRecv < 120) { ssize_t numBytesRcvd = recv(csock, buffer + totalRecv, 120 - totalRecv, 0); if(numBytesRcvd <= 0) { DieWithSystemMessage("recv() failed!"); } totalRecv += numBytesRcvd; } fputs("收到信息来自:", stdout); fputs(buffer, stdout); fputc('\n', stdout); } return (NULL); }
自定义的接口函数:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include "practical.h" #include <stdbool.h> #include <arpa/inet.h> static const int MAXPENDING = 5; // Maximum outstanding connection requests void DieWithUserMessage(const char *msg, const char *detail) { fputs(msg, stderr); fputs(":", stderr); fputs(detail, stderr); fputc('\n', stderr); exit(1); } void DieWithSystemMessage(const char *msg) { perror(msg); exit(1); } int SetupTCPClientSocket(const char *host, const char *service) { //Tell the system what kinds of address info we want struct addrinfo addrCriteria; // Criteria for address match memset(&addrCriteria, 0, sizeof(addrCriteria)); // Zero out structure addrCriteria.ai_family = AF_UNSPEC; addrCriteria.ai_socktype = SOCK_STREAM; addrCriteria.ai_protocol = IPPROTO_TCP; // Get address(es) struct addrinfo *servAddr; //holder for returned list of server addrs int returnVal = getaddrinfo(host, service, &addrCriteria, &servAddr); if(returnVal != 0) { DieWithUserMessage("getaddrinfo() failed", "budong"); } int sock = -1; struct addrinfo *addr; for(addr = servAddr; addr != NULL; addr = addr->ai_next) { //Create a reliable, stream socket using TCP sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if(sock < 0) continue; //Establish the connection to the echo server if(connect(sock, addr->ai_addr, addr->ai_addrlen) == 0) { break; } close(sock); sock = -1; } freeaddrinfo(servAddr); //Free addrinfo allocated in getaddrinfo() return sock; } void PrintSocketAddress(const struct sockaddr *address, FILE *stream) { //Test for address and stream if(address == NULL || stream == NULL) { return; } void *numericAddress; //Pointer to binary address //Buffer to contain result(IPV6 sufficient to hold IPv4) char addrBuffer[INET6_ADDRSTRLEN]; in_port_t port; //Port to print //Set pointer to address based on address family switch(address->sa_family) { case AF_INET: numericAddress = &((struct sockaddr_in*)address)->sin_addr; port = ntohs(((struct sockaddr_in*)address)->sin_port); break; case AF_INET6: numericAddress = &((struct sockaddr_in6*)address)->sin6_addr; port = ntohs(((struct sockaddr_in6*)address)->sin6_port); break; default: fputs("[unknown type]", stream); return; } //Convert binary to printable address if(inet_ntop(address->sa_family, numericAddress, addrBuffer, sizeof(addrBuffer)) == NULL) { fputs("[invalid address]", stream); } else { fprintf(stream, "%s", addrBuffer); if(port != 0) //Zero not valid in any socket addr fprintf(stream, "-%u", port); } } int SetupTCPServerSocket(const char *service) { //Construct the server address structure struct addrinfo addrCriteria; memset(&addrCriteria, 0, sizeof(addrCriteria)); addrCriteria.ai_family = AF_UNSPEC; addrCriteria.ai_flags = AI_PASSIVE; addrCriteria.ai_socktype = SOCK_STREAM; addrCriteria.ai_protocol = IPPROTO_TCP; struct addrinfo *servAddr; //List of server addresses int returnVal = getaddrinfo(NULL, service, &addrCriteria, &servAddr); if(returnVal != 0) { DieWithUserMessage("getaddrinfo() failed", "budong"); } int servSock = -1; struct addrinfo *addr; for(addr = servAddr; addr != NULL; addr = addr->ai_next) { //Create a TCP socket servSock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if(servSock < 0) continue; if((bind(servSock, addr->ai_addr, addr->ai_addrlen) == 0) && (listen(servSock, MAXPENDING) == 0)) { //Print local address of socket struct sockaddr_storage localAddr; socklen_t addrSize = sizeof(localAddr); if(getsockname(servSock, (struct sockaddr*)&localAddr, &addrSize) < 0) { DieWithSystemMessage("getsockname() failed!"); } fputs("Binding to", stdout); PrintSocketAddress((struct sockaddr*)&localAddr, stdout); fputc('\n', stdout); break; } close(servSock); servSock = -1; } //free address list allocated by getaddrinfo() freeaddrinfo(servAddr); return servSock; } int AcceptTCPConnection(int servSock) { struct sockaddr_storage clientAddr; socklen_t clientAddrLen = sizeof(clientAddr); int clientSock = accept(servSock, (struct sockaddr*)&clientAddr, &clientAddrLen); if(clientSock < 0) { DieWithSystemMessage("accept() failed!"); } fputs("handling client", stdout); PrintSocketAddress((struct sockaddr*)&clientAddr, stdout); fputc('\n', stdout); return clientSock; } void nameland(int sock) { char *namemessage = (char*)malloc(20); while(1) { printf("Please input your name:"); scanf("%s", namemessage); size_t namemessageLen = strlen(namemessage); ssize_t numBytes = send(sock, namemessage, namemessageLen, 0); if(numBytes < 0) { DieWithSystemMessage("Send() failed"); } else if(numBytes != namemessageLen) { DieWithUserMessage("send()", "send unexpected number of bytes"); } numBytes = recv(sock, namemessage, 20, 0); if(numBytes <= 0) { DieWithSystemMessage("recv namemessage() failed"); } if(strcmp(namemessage, "the name existed") != 0) break; else printf("the name has existed, please try it again"); } printf("%s\n", namemessage); }
自定义接口函数的头文件为(Practical.h):
#include <stdio.h> void DieWithUserMessage(const char *msg, const char *detail); void DieWithSystemMessage(const char *msg); int SetupTCPClientSocket(const char *host, const char *service); void PrintSocketAddress(const struct sockaddr *address, FILE *stream); int SetupTCPServerSocket(const char *service); int AcceptTCPConnection(int servSock); void nameland(int sock);
服务器端程序的编译命令如下:
gcc server.c Practical.c -lpthread -o server
客户端程序的编译命令如下:
gcc client.c Practical.c -lpthread -o client
一、pstack
64位Linux下已找不到相应的pstack工具
二、strace
strace显示了程序运行过程中所有的系统调用。以下是使用strace工具对运行的服务器端程序server和客户端程序client的系统调用的跟踪情况
strace ./server 5050
fantasy@ubuntu:~/Documents$ strace ./server 5050 execve("./server", ["./server", "5050"], [/* 41 vars */]) = 0 brk(0) = 0x12d6000 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffde6687000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=101060, ...}) = 0 mmap(NULL, 101060, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ffde666e000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/libpthread.so.0", O_RDONLY) = 3 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360Y\0\0\0\0\0\0"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0755, st_size=135745, ...}) = 0 mmap(NULL, 2212736, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ffde624d000 mprotect(0x7ffde6265000, 2093056, PROT_NONE) = 0 mmap(0x7ffde6464000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x17000) = 0x7ffde6464000 mmap(0x7ffde6466000, 13184, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffde6466000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/libc.so.6", O_RDONLY) = 3 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\355\1\0\0\0\0\0"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0755, st_size=1584520, ...}) = 0 mmap(NULL, 3692584, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ffde5ec7000 mprotect(0x7ffde6044000, 2093056, PROT_NONE) = 0 mmap(0x7ffde6243000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x17c000) = 0x7ffde6243000 mmap(0x7ffde6248000, 18472, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffde6248000 close(3) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffde666d000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffde666c000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffde666b000 arch_prctl(ARCH_SET_FS, 0x7ffde666c700) = 0 mprotect(0x7ffde6243000, 16384, PROT_READ) = 0 mprotect(0x7ffde6464000, 4096, PROT_READ) = 0 mprotect(0x602000, 4096, PROT_READ) = 0 mprotect(0x7ffde6689000, 4096, PROT_READ) = 0 munmap(0x7ffde666e000, 101060) = 0 set_tid_address(0x7ffde666c9d0) = 3893 set_robust_list(0x7ffde666c9e0, 0x18) = 0 futex(0x7fff5c86f0bc, FUTEX_WAKE_PRIVATE, 1) = 0 futex(0x7fff5c86f0bc, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 1, NULL, 7ffde666c700) = -1 EAGAIN (Resource temporarily unavailable) rt_sigaction(SIGRTMIN, {0x7ffde6252870, [], SA_RESTORER|SA_SIGINFO, 0x7ffde625c8f0}, NULL, 8) = 0 rt_sigaction(SIGRT_1, {0x7ffde6252900, [], SA_RESTORER|SA_RESTART|SA_SIGINFO, 0x7ffde625c8f0}, NULL, 8) = 0 rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0 getrlimit(RLIMIT_STACK, {rlim_cur=8192*1024, rlim_max=RLIM_INFINITY}) = 0 brk(0) = 0x12d6000 brk(0x12f7000) = 0x12f7000 socket(PF_NETLINK, SOCK_RAW, 0) = 3 bind(3, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 0 getsockname(3, {sa_family=AF_NETLINK, pid=3893, groups=00000000}, [12]) = 0 sendto(3, "\24\0\0\0\26\0\1\3\2109\230Q\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20 recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"0\0\0\0\24\0\2\0\2109\230Q5\17\0\0\2\10\200\376\1\0\0\0\10\0\1\0\177\0\0\1"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 108 recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"@\0\0\0\24\0\2\0\2109\230Q5\17\0\0\n\200\200\376\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 128 recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\24\0\0\0\3\0\2\0\2109\230Q5\17\0\0\0\0\0\0\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 20 close(3) = 0 open("/etc/gai.conf", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=2987, ...}) = 0 fstat(3, {st_mode=S_IFREG|0644, st_size=2987, ...}) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffde6686000 read(3, "# Configuration for getaddrinfo("..., 4096) = 2987 read(3, "", 4096) = 0 close(3) = 0 munmap(0x7ffde6686000, 4096) = 0 futex(0x7ffde6249e04, FUTEX_WAKE_PRIVATE, 2147483647) = 0 socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 3 connect(3, {sa_family=AF_INET6, sin6_port=htons(5050), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = 0 getsockname(3, {sa_family=AF_INET6, sin6_port=htons(54539), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 0 connect(3, {sa_family=AF_UNSPEC, sa_data="\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}, 16) = 0 connect(3, {sa_family=AF_INET, sin_port=htons(5050), sin_addr=inet_addr("0.0.0.0")}, 16) = 0 getsockname(3, {sa_family=AF_INET6, sin6_port=htons(45246), inet_pton(AF_INET6, "::ffff:127.0.0.1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 0 close(3) = 0 socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 3 bind(3, {sa_family=AF_INET, sin_port=htons(5050), sin_addr=inet_addr("0.0.0.0")}, 16) = 0 listen(3, 5) = 0 getsockname(3, {sa_family=AF_INET, sin_port=htons(5050), sin_addr=inet_addr("0.0.0.0")}, [16]) = 0 fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffde6686000 write(1, "Binding to0.0.0.0-5050\n", 23Binding to0.0.0.0-5050 ) = 23 accept(3, {sa_family=AF_INET, sin_port=htons(45717), sin_addr=inet_addr("192.168.134.128")}, [16]) = 4 write(1, "handling client192.168.134.128-4"..., 37handling client192.168.134.128-45717 ) = 37 mmap(NULL, 8392704, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7ffde56c6000 mprotect(0x7ffde56c6000, 4096, PROT_NONE) = 0 clone(child_stack=0x7ffde5ec5ff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7ffde5ec69d0, tls=0x7ffde5ec6700, child_tidptr=0x7ffde5ec69d0) = 3896 accept(3, 接入用户名:fantasy 收到:fantasy:hello to: fantasy:hello
strace ./client 192.168.134.128 5050
fantasy@ubuntu:~/Documents$ strace ./client 192.168.134.128 5050 execve("./client", ["./client", "192.168.134.128", "5050"], [/* 40 vars */]) = 0 brk(0) = 0x1bb1000 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd016708000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=101060, ...}) = 0 mmap(NULL, 101060, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fd0166ef000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/libpthread.so.0", O_RDONLY) = 3 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360Y\0\0\0\0\0\0"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0755, st_size=135745, ...}) = 0 mmap(NULL, 2212736, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fd0162ce000 mprotect(0x7fd0162e6000, 2093056, PROT_NONE) = 0 mmap(0x7fd0164e5000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x17000) = 0x7fd0164e5000 mmap(0x7fd0164e7000, 13184, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fd0164e7000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/libc.so.6", O_RDONLY) = 3 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\355\1\0\0\0\0\0"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0755, st_size=1584520, ...}) = 0 mmap(NULL, 3692584, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fd015f48000 mprotect(0x7fd0160c5000, 2093056, PROT_NONE) = 0 mmap(0x7fd0162c4000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x17c000) = 0x7fd0162c4000 mmap(0x7fd0162c9000, 18472, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fd0162c9000 close(3) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd0166ee000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd0166ed000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd0166ec000 arch_prctl(ARCH_SET_FS, 0x7fd0166ed700) = 0 mprotect(0x7fd0162c4000, 16384, PROT_READ) = 0 mprotect(0x7fd0164e5000, 4096, PROT_READ) = 0 mprotect(0x602000, 4096, PROT_READ) = 0 mprotect(0x7fd01670a000, 4096, PROT_READ) = 0 munmap(0x7fd0166ef000, 101060) = 0 set_tid_address(0x7fd0166ed9d0) = 3895 set_robust_list(0x7fd0166ed9e0, 0x18) = 0 futex(0x7fff9fe5b15c, FUTEX_WAKE_PRIVATE, 1) = 0 futex(0x7fff9fe5b15c, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 1, NULL, 7fd0166ed700) = -1 EAGAIN (Resource temporarily unavailable) rt_sigaction(SIGRTMIN, {0x7fd0162d3870, [], SA_RESTORER|SA_SIGINFO, 0x7fd0162dd8f0}, NULL, 8) = 0 rt_sigaction(SIGRT_1, {0x7fd0162d3900, [], SA_RESTORER|SA_RESTART|SA_SIGINFO, 0x7fd0162dd8f0}, NULL, 8) = 0 rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0 getrlimit(RLIMIT_STACK, {rlim_cur=8192*1024, rlim_max=RLIM_INFINITY}) = 0 brk(0) = 0x1bb1000 brk(0x1bd2000) = 0x1bd2000 socket(PF_NETLINK, SOCK_RAW, 0) = 3 bind(3, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 0 getsockname(3, {sa_family=AF_NETLINK, pid=3895, groups=00000000}, [12]) = 0 sendto(3, "\24\0\0\0\26\0\1\3\2179\230Q\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20 recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"0\0\0\0\24\0\2\0\2179\230Q7\17\0\0\2\10\200\376\1\0\0\0\10\0\1\0\177\0\0\1"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 108 recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"@\0\0\0\24\0\2\0\2179\230Q7\17\0\0\n\200\200\376\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 128 recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\24\0\0\0\3\0\2\0\2179\230Q7\17\0\0\0\0\0\0\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 20 close(3) = 0 socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 3 connect(3, {sa_family=AF_INET, sin_port=htons(5050), sin_addr=inet_addr("192.168.134.128")}, 16) = 0 fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd016707000 fstat(0, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd016706000 write(1, "Please input your name:", 23Please input your name:) = 23 read(0, fantasy "fantasy\n", 1024) = 8 sendto(3, "fantasy", 7, 0, NULL, 0) = 7 recvfrom(3, "Land Success\0", 20, 0, NULL, NULL) = 13 write(1, "Land Success\n", 13Land Success ) = 13 mmap(NULL, 8392704, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7fd015747000 mprotect(0x7fd015747000, 4096, PROT_NONE) = 0 clone(child_stack=0x7fd015f46ff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7fd015f479d0, tls=0x7fd015f47700, child_tidptr=0x7fd015f479d0) = 3898 write(1, "|-------\347\231\273\351\231\206\346\210\220\345\212\237\350\257\267\346\214\211\346\255\244\346\240\274"..., 76|-------登陆成功请按此格式聊天(用户名:信息内容)---------| ) = 76 write(1, "|--------(\344\277\241\346\201\257\346\234\200\351\225\277100\345\255\227\347\254\246/"..., 100|--------(信息最长100字符/使用list命令获取在线用户列表/close命令退出)-------| ) = 100 read(0, fantasy:hello "fantasy:hello\n", 1024) = 14 sendto(3, "fantasy:hello\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 120, 0, NULL, 0) = 120 write(1, "\345\217\221\351\200\201\345\255\227\350\212\202\346\225\260:120\n", 20发送字节数:120 ) = 20 read(0, 收到信息来自:fantasy:hello
三、valgrind
valgrind 是帮助程序员寻找程序里的 bug 和改进程序性能的工具。程序通过 valgrind 运行时,valgrind 收集各种有用的信息,通过这些信息可以找到程序中潜在的 bug 和性能瓶颈。
Valgrind 现在提供多个工具,其中最重要的是 Memcheck,Cachegrind,Massif 和 Callgrind。Valgrind 是在 Linux 系统下开发应用程序时用于调试内存问题的工具。它尤其擅长发现内存管理的问题,它可以检查程序运行时的内存泄漏问题。其中的 memecheck 工具可以用来寻找 c、c++ 程序中内存管理的错误。可以检查出下列几种内存操作上的错误:
读写已经释放的内存
读写内存块越界(从前或者从后)
使用还未初始化的变量
将无意义的参数传递给系统调用
内存泄漏
参考:
http://blog.csdn.net/icechenbing/article/details/7794439
http://wenku.baidu.com/view/88bc81067cd184254b3535b1.html
http://www.bitscn.com/os/linux/201101/192667_2.html
http://www.ibm.com/developerworks/cn/linux/l-mleak/