目的是连接文件夹中的某些文件模式。让我们说一个名为
的文件夹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]);
}
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;
}