多線程同時寫文件可能存在的問題:
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;
}