如何让一个进程处理队列操作,而另一个进程执行队列中的查询

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

在下面的代码(服务器)中,我需要能够接收客户端的查询,将它们插入 FCFS 队列中,同时,我需要服务器执行这些查询。 我知道下面的代码不能满足我的需要,而且我不知道如何做到这一点。我不能使用信号量、多线程等。如果需要的话,我只允许使用叉子和管道。 我知道我需要在这两个进程之间使用管道,但我不知道如何使用。

服务器.C

#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>

int main (int argc, char* argv[]) {

    char** queue = malloc(sizeof (char*) * 15);
    int queue_size = 0;

    if (mkfifo("fifo", 0666) == -1) {
        perror("mkfifo");
        return 1;
    }

    int fd_server = open("fifo", O_RDONLY);
    
    Queue* fcfs_queue = malloc(sizeof(Queue));
    newQueue(fcfs_queue);

    int pid_enqueue = fork();
    if (pid_enqueue == -1) {
        return 1;
    }

    if (pid_enqueue == 0) { //read the input from the client
        while(1) {
            if (fcfs_queue->head != NULL) {
                printf("%s\n", fcfs_queue->head->data);
                deQueue(fcfs_queue);
            }
        }
        _exit(0);
    } else {
        while(1) {
            char* toRead = malloc(sizeof(char) * 15);
            ssize_t bytes_read = read(fd_server, toRead, sizeof(char) * 15);
            if (bytes_read > 0) {
                enQueue(fcfs_queue, toRead);
            }
        }
    }

    close(fd_server);



    return 0;
}   

客户端.C

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

int main (int argc, char* argv[]) {
    //argv[1] must have less that 16 characters

    int fd_server = open("fifo", O_WRONLY);
    if (fd_server == -1) {
        perror("server");
        return 1;
    }
    char* toWrite = strdup(argv[1]);
    strcpy(toWrite, argv[1]);
    ssize_t bytes_written = write(fd_server, toWrite, strlen(toWrite) + 1);
    printf("%d", bytes_written);
    close(fd_server);

    return 0;

}

QUEUE_MANAGER.C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Node {
    char* data;
    struct Node* next;
} Node;

typedef struct {
    Node* head;
    Node* tail;
    int tamanho;
} Queue;

void newQueue(Queue* aux) {
    aux->head = NULL;
    aux->tail = NULL;
    aux->tamanho = 0;
}

void enQueue(Queue* fila, char* toInsert) {
    Node* newNode = malloc(sizeof(Node));
    if (!newNode) {
        perror("malloc");
        return;
    }
    newNode->data = strdup(toInsert); 
    newNode->next = NULL;

    if (fila->tail != NULL) {
        fila->tail->next = newNode;
    }
    fila->tail = newNode;

    if (fila->head == NULL) {
        fila->head = newNode;
    }

    fila->tamanho++;
}


void deQueue(Queue* fila) {
    if (fila->head != NULL) {
        Node* temp = fila->head;
        fila->head = fila->head->next;
        free(temp->data);
        free(temp);
        if (fila->head == NULL) {
            fila->tail = NULL;
        }
        fila->tamanho--;
    }
}

我已经尝试让服务器请求子进程(如果他可以处理队列), 如果是这样我们就会执行。我在此解决方案中使用了两个管道,但它不起作用。

c server pipe fork
1个回答
0
投票

你们非常接近...

  1. 服务器不需要需要
    fork
    。这会破坏队列,因为服务器的子级写入与服务器父级不同的内存。
  2. 因为管道可以有“短读”或“短写”,所以我们可以使用
    fdopen
    来获取流。
  3. 您的队列没问题

服务器需要两个循环:

  1. 从管道读取命令并将它们排入队列。
  2. 出队并处理命令

这是修改后的

server.c
(我已合并到
queue.c
):

#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>

typedef struct Node {
    char *data;
    struct Node *next;
} Node;

typedef struct {
    Node *head;
    Node *tail;
    int tamanho;
} Queue;

void
newQueue(Queue *aux)
{
    aux->head = NULL;
    aux->tail = NULL;
    aux->tamanho = 0;
}

void
enQueue(Queue *fila, char *toInsert)
{
    Node *newNode = malloc(sizeof(Node));

    if (!newNode) {
        perror("malloc");
        return;
    }

    newNode->data = strdup(toInsert);
    newNode->next = NULL;

    if (fila->tail != NULL) {
        fila->tail->next = newNode;
    }
    fila->tail = newNode;

    if (fila->head == NULL)
        fila->head = newNode;

    fila->tamanho++;
}

void
deQueue(Queue *fila)
{
    Node *temp = fila->head;

    if (temp != NULL) {
        fila->head = temp->next;

        free(temp->data);
        free(temp);

        if (fila->tail == temp)
            fila->tail = NULL;

        fila->tamanho--;
    }
}

int
main(int argc, char *argv[])
{

    if (mkfifo("fifo", 0666) == -1) {
        perror("mkfifo");
        return 1;
    }

    int fd_server = open("fifo", O_RDONLY);
    FILE *fi = fdopen(fd_server,"r");

    Queue *fcfs_queue = malloc(sizeof(Queue));
    newQueue(fcfs_queue);

    char toRead[1000];

    while (1) {
        char *cp = fgets(toRead,sizeof(toRead),fi);
        if (cp == NULL)
            break;

        // strip newline
        toRead[strcspn(toRead,"\n")] = 0;

        enQueue(fcfs_queue,toRead);
    }

    fclose(fi);

    while (1) {
        Node *cur = fcfs_queue->head;
        if (cur == NULL)
            break;

        printf("%s\n", cur->data);
        deQueue(fcfs_queue);
    }

    return 0;
}

这是修改后的

client.c

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

int
main(int argc, char *argv[])
{
    // argv[1] must have less that 16 characters

    // skip over program name
    --argc;
    ++argv;

    int fd_server = open("fifo", O_WRONLY);

    if (fd_server == -1) {
        perror("server");
        return 1;
    }

// NOTE: strdup not needed
#if 0
    char *toWrite = strdup(argv[1]);
    strcpy(toWrite, argv[1]);
#else
    char *toWrite;
#endif

#if 1
    FILE *fo = fdopen(fd_server,"w");
#endif

#if 0
    ssize_t bytes_written = write(fd_server, toWrite, strlen(toWrite) + 1);
    printf("%d", bytes_written);
    close(fd_server);
#else
    for (;  argc > 0;  --argc, ++argv) {
        toWrite = *argv;
        fputs(toWrite,fo);
        fputc('\n',fo);
    }
    fclose(fo);
#endif

    return 0;

}

在上面的代码中,我使用

cpp
条件来表示旧代码与新代码:

#if 0
// old code
#else
// new code
#endif

#if 1
// new code
#endif

注意:这可以通过运行文件来清理

unifdef -k


这是客户端命令:

./client quick brown fox jumps over the lazy dog

这是服务器输出:

quick
brown
fox
jumps
over
the
lazy
dog
© www.soinside.com 2019 - 2024. All rights reserved.