write 操作文件注意事項

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章