除了通用的对一段一段程序进行时间复杂度和空间复杂度进行分析以外,还可以将strace和pstack工具结合起来使用,直接用来找到影响程序运行时间的函数调用,再有针对地对相关函数进行代码分析和优化,对于几万行的代码的大型项目来说,该方法比漫无目的的看代码效率高很多。
其中,
strace跟踪程序使用的底层系统调用,可输出系统调用被执行的时间点以及各个调用耗时;
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);
}
客户端程序 client.c
#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.youkuaiyun.com/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/