C 中的 IPC 队列 - 动态大小的消息

问题描述 投票:0回答:1

目的是连接文件夹中的某些文件模式。让我们说一个名为

的文件夹
abc 

有带子字符串的文件

score

像score_01.csv、score_02.csv、score_03.csv以及同样的数百个文件

下面程序的基本概念是接受两个命令行参数,一个是文件夹,另一个是文件模式。

gcc program.c -o program
./program my_folder score

程序进入 my_folder 并开始遍历文件,读取它们,然后将它们推入 IPC 队列。并且有一个消费者在程序的开头使用 pthread 启动。该消费者必须阅读并打印。

我似乎没有正确执行 msgsnd 或 msgrcv

此外,如果我尝试在 msgsnd 之前打印数据缓冲区,它在 Mac OS 中的打印方式会有所不同 - 没有问题,而在 Ubuntu 中,它会打印几行,然后出现分散的文本

// File name program.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>


key_t key;
int msgid;

typedef struct {
    long msg_type;
    char* buffer;
    size_t length;
} bufferPack;


char* fileBuffer(char* filename) {
    FILE *f = fopen(filename, "rb");
    fseek(f, 0, SEEK_END);
    long fsize = ftell(f);
    fseek(f, 0, SEEK_SET); 
    char *string = malloc(fsize + 1);
    fread(string, fsize, 1, f);
    fclose(f);
    return string;
} 

void walk_dir(const char *path, char* wildcard)
{
    DIR *dir;
    struct dirent *entry;

    if (!(dir = opendir(path)))
        return;

    while ((entry = readdir(dir)) != NULL) {
        char *name = entry->d_name;
        char full_name[1024];

        if (strstr(name, wildcard ) == NULL )
            continue;

        snprintf(full_name, sizeof(full_name), "%s/%s", path, name);
        bufferPack pack;
        pack.msg_type = 1;
        pack.buffer = fileBuffer(full_name);
        pack.length = strlen(pack.buffer);
        msgsnd(msgid, &pack, sizeof(bufferPack), 0);
    }
    closedir(dir);
}

void* consumer(void* arg) {
    bufferPack pack; 
    while (1) {
        int rec = msgrcv(msgid, &pack, sizeof(bufferPack), 1, 0);    
        if (rec == -1) 
            // No message in queue
            continue;
        printf("%s\n", pack.buffer);
        free(pack.buffer);
    }
}

int main(int argc, char **argv)
{
    if ((key = ftok("/tmp", 'A')) == -1) {
        perror("ftok");
        exit(EXIT_FAILURE);
    }

    if ((msgid = msgget(key, 0666 | IPC_CREAT)) == -1) {
        perror("msgget");
        exit(EXIT_FAILURE);
    }

    pthread_t thread;                             
    pthread_create(&thread, NULL, consumer, NULL);

    walk_dir(argv[1], argv[2]);
}
c ipc
1个回答
0
投票

strlen(pack.buffer)
要求缓冲区是一个以 null 结尾的字符串。但是
fileBuffer()
永远不会添加空终止符(尽管它使用
fsize+1
为其分配了空间)。

char* fileBuffer(char* filename) {
    FILE *f = fopen(filename, "rb");
    fseek(f, 0, SEEK_END);
    long fsize = ftell(f);
    fseek(f, 0, SEEK_SET); 
    char *string = malloc(fsize + 1);
    fread(string, fsize, 1, f);
    string[fsize] = '\0'; // add null terminator
    fclose(f);
    return string;
} 
© www.soinside.com 2019 - 2024. All rights reserved.