在C中写入文件多线程

时间:2014-06-29 23:44:26

标签: c multithreading file file-io

我首先尝试在main()中打开文件,但是当我的消费者线程尝试使用fputs写入或使用fseek更改文件指针时,我收到了分段错误。

所以我尝试打开文件并写入线程临界区内的文件。这次没有错误,但文件不正确。除最后一个字符外的每个字符都是“NUL”符号。
例如:
预期:abcdefg
结果:NULNULNULNULNULNULNULg

这是我的消费者主题:

void *OUTthread(void *arg)
{

    FILE *targetFile;
    struct timespec t;
    t.tv_sec = 0;
    t.tv_nsec = rand()%(TEN_MILLIS_IN_NANOS+1);
    nanosleep(&t, NULL);

    BufferItem OUTresult;

    while(TRUE){

        /*** CRITICAL SECTION *************************/
        sem_wait(&full);
        pthread_mutex_lock( &pt_mutex );
        cbRead(&cBuff, &OUTresult);
        printf("From buffer: offset %d char %c\n", OUTresult.offset, OUTresult.data); 
        // The data printed to stdout is correct, so why is it NUL in the file?

        if (!(targetFile = fopen(arg, "w+"))) {
            printf("could not open output file for writing");
        }
        if (fseek(targetFile, OUTresult.offset, SEEK_SET) == -1) {
            fprintf(stderr, "error setting output file position to %u\n",
                    (unsigned int) OUTresult.offset);
            exit(-1);
        }
        if (fputc(OUTresult.data, targetFile) == EOF) {
            fprintf(stderr, "error writing byte %d to output file\n", OUTresult.data);
            exit(-1);
        }
        fclose(targetFile);
        pthread_mutex_unlock( &pt_mutex );
        sem_post(&empty); /* signal empty */
        /*** END CRITICAL SECTION ****************************/

        t.tv_sec = 0;
        t.tv_nsec = rand()%(TEN_MILLIS_IN_NANOS+1);
        nanosleep(&t, NULL);

    }

    pthread_exit(0);

}

修改

bufferItem

typedef  struct {
     char  data ;
     off_t offset ; // Position of the char.
} BufferItem ;

这是读取循环缓冲区中最旧项目的函数。

void cbRead(CircularBuffer *cb, BufferItem *cbItem) {
    *cbItem = cb->cBuffItems[cb->startInd];
    cb->startInd = (cb->startInd + 1) % cb->size;
}

如果需要,这是循环缓冲区实现的其余部分:

// Circular buffer
typedef struct {
    int startInd; // Index of first element added to buffer.
    int lastInd; // Index of most recent element added to buffer.
    int size; // Number of elements in circular buffer.
    BufferItem *cBuffItems; // Circular buffer items.
} CircularBuffer;

void addItem(CircularBuffer *cBuff, BufferItem *cbItem) {
    cBuff->cBuffItems[cBuff->lastInd] = *cbItem;
    cBuff->lastInd = ( ((cBuff->lastInd) + 1) % cBuff->size);
    if (cBuff->lastInd == cBuff->startInd)
    {
        cBuff->startInd = (cBuff->startInd + 1) % cBuff->size; // Overwriting full buffer.
    }
}


void initializeBuffer(CircularBuffer *cBuff, int size) {
    cBuff->cBuffItems = calloc(size + 1, sizeof(BufferItem));
    cBuff->size  = size + 1;
    cBuff->startInd = 0;
    cBuff->lastInd   = 0;
}

int cbIsEmpty(CircularBuffer *cb) {
    return cb->lastInd == cb->startInd;
}

1 个答案:

答案 0 :(得分:3)

对我来说,问题是打开文件" w +"模式。 w +丢弃以前的内容。每当您的消费者打开文件(再次)时,您会得到一个截断的文件,然后您寻找一个位置并写一个字符。这会丢弃所有以前的数据,所以最后会获胜,并解释为什么你会看到上一个消费者的角色,每个先前的消息都为空前填充"寻找"

http://www.cplusplus.com/reference/cstdio/fopen/

尝试打开" r +"如果该呼叫失败,则回到" w +" (或者只使用单个fopen和#34; a"如果你不需要更新以前的内容)。你也可以先用stat()来检查是否存在,尽管这实际上是fopen(" r +")的作用。