最近做的一个任务,是在一个线程中不断接收UDP包,并将包dump到文件内。
代码这么写:
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>//Linux system call for thread id
#include <assert.h>
#include <pthread.h>
void logMsg()
{
int loop = 0;
FILE *fp = fopen("/tmp/mo_send.txt", "w");
if (loop < 100)
fprintf(fp, "%d\n", loop);
else if (100 == loop)
fclose(fp);
loop++;
}
void *nbi(void *arg)
{
printf("child thread lwpid = %u\n", syscall(SYS_gettid));
while (1)
{
logMsg();
usleep(50*1000);
}
}
int main()
{
pthread_t tid;
int rc;
printf("main thread lwpid = %u\n", syscall(SYS_gettid));
rc = pthread_create(&tid, NULL, nbi, NULL);
assert(0 == rc);
pthread_join(tid, NULL);
return 0;
}
运行完毕后,查看log文件,空文件!
思索良久后才发现是一个低级错误:C局部变量每次都初始化,导致文件重复打开,并将上次写入的内容冲走,但是文件句柄放到函数外部也不好,怕污染名称空间,于是想到了static修饰符。
直接给loop和fp前面加static会报错:
f_test.c: In function 'logMsg':
f_test.c:9:2: error: initializer element is not constant
static FILE *fp = fopen("/tmp/mo_send.txt", "w");
^
原来静态变量本质上跟全局变量一样,只能用常量来初始化,只是编译器在限制了其scope而已。
再改代码:
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>//Linux system call for thread id
#include <assert.h>
#include <pthread.h>
void logMsg()
{
static int loop = 0;
static FILE *fp = NULL;
if (NULL == fp)
fp = fopen("/tmp/mo_send.txt", "w");
if (loop < 100)
fprintf(fp, "%d\n", loop);
else if (100 == loop)
fclose(fp);
loop++;
}
void *nbi(void *arg)
{
printf("child thread lwpid = %u\n", syscall(SYS_gettid));
while (1)
{
logMsg();
usleep(50*1000);
}
}
int main()
{
pthread_t tid;
int rc;
printf("main thread lwpid = %u\n", syscall(SYS_gettid));
rc = pthread_create(&tid, NULL, nbi, NULL);
assert(0 == rc);
pthread_join(tid, NULL);
return 0;
}
再运行就log文件就正常了。