多线程同时写文件可能存在的问题: 1.文件被另一个线程占用,fd不可写,导致write失败; 2.write 拷贝大量数据到文件时,一次操作不能全部写入,需要循环检测,重复写入才能保证数据完整性。
typedef struct LocoTty_s { U32 tid; /**< the tty id */ S32 stdin; /**< the stdin of the tty */ S32 stdout; /**< the stdout of the tty */ S32 stderr; /**< the stderr of the tty */ char name[MAX_TTY_NAME]; /**< the name of the tty */ int fd; /**< the file description of the tty */ Boolean isReady; /**< true when the fd is ready to write */ Boolean isSync; /**< support sync */ Boolean isRetry; /**< support retry */ LocoTtyType type; /**< the type of tty */ PROCESS pid; /**< the pid of loco_coli */ OSATTREF attachRef; /**< the attach reference of loco_coli */ Boolean isRel; /**< release tty after the command */ } LocoTty</span>;
Solution is displayed below,FIY:
/** * @brief check the fd can write. to detect the fd by select()... * */ static int checkFdReady(U32 tid) { LocoTty *tty = getTty(tid); fd_set wfds; struct timeval tv; int retval; if(NULL == tty || tty->fd < 0) { return LOCO_PARAM_NULL_PTR; } /* Watch the fid of tid to see when it has input. */ FD_ZERO(&wfds); FD_SET(tty->fd, &wfds); /* Wait up to a little time. */ tv.tv_sec = 1; tv.tv_usec = 0; retval = select(tty->fd + 1, NULL, &wfds, NULL, &tv); if(retval == -1) { TRACE_ERROR(STR("select error: fd=%d,errno=%d", tty->fd, errno)); } else if(0 != retval) { if(FD_ISSET(tty->fd, &wfds)) { tty->isReady = True; } else { TRACE_ERROR(STR("fd %d is not in wfds.\n", tty->fd)); } } else { if(tty->isReady) { INFO(STR("Tty not ready: tid=%d,fd=%d,name=%s.\n", tty->tid, tty->fd, tty->name)); isReady = False; } } return LOCO_OK; } /** * @brief write buf to file referred to by the fd * * @param tid tty id * @param buf data buffer */ static int writeBuffer(U32 tid, const char *buf) { int len = 0; int olen = strlen(buf); int buflen = 0; int checkcount = 0; len = write(sTty[tid].fd, buf, olen); if(len != olen) { while(sTty[tid].isRetry && checkcount < 3 && len < olen) { /* check the output is ready, wait 1 sec every check*/ (void)checkFdReady(tid); if(len > 0) { olen = olen - len; buflen += len; checkcount = 0; } len = write(sTty[tid].fd, buf + buflen, olen); if(len < 0) { INFO(STR("write:tid=%d, fd=%d,len=%d, str=%d,errno=%d", tid, sTty[tid].fd, len, olen, errno)); checkcount++; continue; } } if(checkcount == 3) { sTty[tid].isRetry = False; return len; } } else { sTty[tid].isRetry = True; } /* force the write. if here is no this function, the line is output immeditely with end of "\r\n". */ int ret = fsync(sTty[tid].fd); if(ret < 0 && sTty[tid].isSync) { INFO(STR("fsync:tid=%d,fd=%d,errno=%d", tid, sTty[tid].fd, errno)); // the fsync will failed when fd is not support fsync. sTty[tid].isSync = False; } return len; }