最近在做一个文件存储功能时遇到的一个问题。在while(1)死循环中open文件,修改里面的数据。close在while外。当注释掉这close时,当终止程序时并不会保存已修改的数据。反之则会保存。不多说直接按上代码。
static gpointer wort_thread(gpointer data)
{
int fd;
int ret;
int i=0;
int nbytes;
struct msghdr msg;
struct ifreq ifr;
fd_set rdfs;
struct sockaddr_can addr;
DisPlayData* disdata=(DisPlayData*)data;
GstElement *png_overlay = GST_PAD_PARENT (disdata->pad_png);
GstElement *text_overlay = GST_PAD_PARENT (disdata->pad_text);
fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
addr.can_family = AF_CAN;
memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
strncpy(ifr.ifr_name, "can0", strlen("can0"));
if(ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
exit(1);
}
addr.can_ifindex = ifr.ifr_ifindex;
setsockopt(fd, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfd_on, sizeof(canfd_on));
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
return NULL;
}
/* set rfilter */
struct can_filter rfilter;
rfilter.can_id = 0x1d5d0002;
rfilter.can_mask = 0x1fffffff;
setsockopt(fd, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));
iov.iov_base = &canframe;
msg.msg_name = &addr;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = &ctrlmsg;
int x, y;
gchar x_pal1_fd, y_pal1_fd, x_pal2_fd, y_pal2_fd, x_camlink_fd, y_camlink_fd;
gchar xbuf[4], ybuf[4];
gchar flag_png = 1;
gchar flag_text = 1;
gchar channel = 0x10; // 初始通道 pal1 = 0x10
if((x_pal1_fd = open("x1.txt",O_RDWR|O_CREAT))< 0){
perror("open");
}
if((y_pal1_fd = open("y1.txt",O_RDWR|O_CREAT))< 0){
perror("open");
}
if( (read(x_pal1_fd, xbuf, 4) && read(y_pal1_fd, ybuf, 4)) == 0){
perror("read or write");
}
x = atoi(xbuf);
y = atoi(ybuf);
g_object_set (png_overlay, "offset-x", x, "offset-y", y, NULL);
set_enum_property_by_name (text_overlay, "valignment", "top");
set_enum_property_by_name (text_overlay, "halignment", "left");
set_enum_property_by_name (text_overlay, "line-alignment", "left");
while(1)
{
FD_ZERO(&rdfs);
FD_SET(fd, &rdfs);
if((ret = select(fd+1, &rdfs, NULL, NULL, NULL)) <= 0) {
perror("select");
continue;
}
if(FD_ISSET(fd, &rdfs))
{
iov.iov_len = sizeof(canframe);
msg.msg_namelen = sizeof(addr);
msg.msg_controllen = sizeof(ctrlmsg);
msg.msg_flags = 0;
nbytes = recvmsg(fd, &msg, 0);
/*
g_print("nbytes %d \r\n",nbytes);
g_print("canframe.can_id%d:",canframe.can_id);
for(i=0;i<8;i++){
g_print("%02X ",canframe.data[i]);
}
*/
switch(canframe.data[0]){
case 0x01:
if(x <= MAX_W){
g_object_set (png_overlay, "offset-x", ++x, "offset-y", y, NULL);
memset(xbuf, 0, 4);
sprintf(xbuf, "%d", x);
if(channel == 0x12){
lseek(x_camlink_fd, 0, SEEK_SET);
write(x_camlink_fd, xbuf, 4);
}
if(channel == 0x10){
lseek(x_pal1_fd, 0, SEEK_SET);
write(x_pal1_fd, xbuf, 4);
}
if(channel == 0x11){
lseek(x_pal2_fd, 0, SEEK_SET);
write(x_pal2_fd, xbuf, 4);
}
} break;
case 0x02:
if(x > 0){
g_object_set (png_overlay, "offset-x", --x, "offset-y", y, NULL);
memset(xbuf, 0, 4);
sprintf(xbuf, "%d", x);
if(channel == 0x12){
lseek(x_camlink_fd, 0, SEEK_SET);
write(x_camlink_fd, xbuf, 4);
}
if(channel == 0x10){
lseek(x_pal1_fd, 0, SEEK_SET);
write(x_pal1_fd, xbuf, 4);
}
if(channel == 0x11){
lseek(x_pal2_fd, 0, SEEK_SET);
write(x_pal2_fd, xbuf, 4);
}
} break;
case 0x03:
if(y <= MAX_H){
g_object_set (png_overlay, "offset-x", x, "offset-y", ++y, NULL);
memset(ybuf, 0, 4);
sprintf(ybuf, "%d", y);
if(channel == 0x12){
lseek(y_camlink_fd, 0, SEEK_SET);
write(y_camlink_fd, ybuf, 4);
}
if(channel == 0x10){
lseek(y_pal1_fd, 0, SEEK_SET);
write(y_pal1_fd, ybuf, 4);
}
if(channel == 0x11){
lseek(y_pal2_fd, 0, SEEK_SET);
write(y_pal2_fd, ybuf, 4);
}
} break;
case 0x04:
if(y > 0){
g_object_set (png_overlay, "offset-x", x, "offset-y", --y, NULL);
memset(ybuf, 0, 4);
sprintf(ybuf, "%d", y);
if(channel == 0x12){
lseek(y_camlink_fd, 0, SEEK_SET);
write(y_camlink_fd, ybuf, 4);
}
if(channel == 0x10){
lseek(y_pal1_fd, 0, SEEK_SET);
write(y_pal1_fd, ybuf, 4);
}
if(channel == 0x11){
lseek(y_pal2_fd, 0, SEEK_SET);
write(y_pal2_fd, ybuf, 4);
}
} break;
case 0x0d:
if(flag_png == 1){
g_object_set (png_overlay, "location","asert.png",NULL);
flag_png = 0;
}break;
case 0x0e:
if(flag_png == 0){
g_object_set (png_overlay, "location","asert1.png",NULL);
flag_png = 1;
}break;
case 0x0f:
if(flag_text == 1){
g_object_set (text_overlay, "text","",NULL);
flag_text = 0;
}break;
/* Switch video lines */
case 0x10:
close(x_pal2_fd);
close(y_pal2_fd);
close(x_camlink_fd);
close(y_camlink_fd);
if((x_pal1_fd = open("x1.txt",O_RDWR|O_CREAT))< 0){
perror("open");
}
if((y_pal1_fd = open("y1.txt",O_RDWR|O_CREAT))< 0){
perror("open");
return NULL;
}
memset(xbuf, 0, 4);
memset(ybuf, 0, 4);
if((read(x_pal1_fd, xbuf, 4) || read(y_pal1_fd, ybuf, 4)) == 0){
perror("read or write");
}
x = atoi(xbuf);
y = atoi(ybuf);
g_object_set (png_overlay, "offset-x", x, "offset-y", y, NULL);
g_object_set (text_overlay, "text","电视大", "font-desc","Sans, 20", "halignment","left",
"valignment","top", "line-alignment","center",NULL);
flag_text = 1; channel = 0x10; break;
case 0x11:
close(x_pal1_fd);
close(y_pal1_fd);
close(x_camlink_fd);
close(y_camlink_fd);
if((x_pal2_fd = open("x2.txt",O_RDWR|O_CREAT))< 0){
perror("open");
}
if((y_pal1_fd = open("y2.txt",O_RDWR|O_CREAT))< 0){
perror("open");
}
memset(xbuf, 0, 4);
memset(ybuf, 0, 4);
if((read(x_pal2_fd, xbuf, 4) || read(y_pal2_fd, ybuf, 4)) == 0){
perror("read or write");
}
x = atoi(xbuf);
y = atoi(ybuf);
g_object_set (png_overlay, "offset-x", x, "offset-y", y, NULL);
g_object_set (text_overlay, "text","电视小", "font-desc","Sans, 20", "halignment","left",
"valignment","top", "line-alignment","center",NULL);
flag_text = 1;channel = 0x11;break;
case 0x12:
close(x_pal2_fd);
close(y_pal2_fd);
close(x_pal1_fd);
close(y_pal1_fd);
if((x_camlink_fd = open("x.txt",O_RDWR|O_CREAT))< 0){
perror("open");
}
if((y_camlink_fd = open("y.txt",O_RDWR|O_CREAT))< 0){
perror("open");
return NULL;
}
memset(xbuf, 0, 4);
memset(ybuf, 0, 4);
if((read(x_camlink_fd, xbuf, 4) || read(y_camlink_fd, ybuf, 4)) == 0){
perror("read or write");
}
x = atoi(xbuf);
y = atoi(ybuf);
g_object_set (png_overlay, "offset-x", x, "offset-y", y, NULL);
g_object_set (text_overlay, "text","热像", "font-desc","Sans, 20", "halignment","left",
"valignment","top", "line-alignment","center",NULL);
flag_text = 1;channel = 0x12;break;
default:break;
}
}
}
// close(x_pal1_fd);
// close(y_pal1_fd);
// close(x_pal2_fd);
// close(y_pal2_fd);
// close(x_camlink_fd);
// close(y_camlink_fd);
return NULL;
}
这段代码的重点在while循环里。
通过查阅close系统调用说明,当一个进程终止时,内核对该进程所有尚未关闭的文件描述符调用close关闭,所以即使用户程序不调用close,在终止时内核也会自动关闭它打开的所有文件。当我注释掉while外面的close时,按ctrl+c或者直接断电终止程序运行,发现修改的数据并没有保存到磁盘里。反之不注释则会保存。(在这一直是懵逼状态没弄清楚怎么回事,和官方说明不一致。)也就是在while(1)里open的文件,终止程序时没调用close时修改的文件并没有保存到磁盘中。而在循环外加了close释放将会实现保存。但是按理说程序并不会执行到while(1)外面的close。
留在这里当做一个备忘录。希望能尽快解决这个问题。