叉子后如何通过键盘在孩子中引入字符串

Posted

技术标签:

【中文标题】叉子后如何通过键盘在孩子中引入字符串【英文标题】:How to introduce string by keyboard in child after fork 【发布时间】:2015-06-08 20:07:35 【问题描述】:

我正在练习 C 中的并发性,我编写了一个小而简单的程序,其中父进程创建了两个子进程,发送者和接收者。 发送者将从标准输入中读取一个字符串,然后以某种方式将其发送给接收者(不相关)。

这里真正的问题是,当我运行程序时,它执行分叉,两个孩子将出生,发件人应该等待一个字符串作为输入,但我找不到使用终端插入任何内容的方法. 该程序似乎挂在scanf上,但我找不到引入任何输入的方法。终端,一旦程序启动,就不允许我插入任何东西。

我使用的是 Xcode 6.3.2

#include <stdio.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#define FILE_NAME "conteggio"
#define MAX_CHAR 25

void receiver();
void sender();

void receiver_operation();
void sender_operation();
void to_maiusc(char s[], char* r);
int readline(int fd, char *str);
void nothing() 

typedef enum FALSE, TRUE boolean;
int sender_pid, receiver_pid;

int main(int argc, const char * argv[]) 
    FILE *f_in;
    int status, num, sender_pid, receiver_pid;
    // create the two childs
    if ( (sender_pid = fork()) != 0 ) 
        // I'm the father
        if ( (receiver_pid = fork()) != 0 ) 
            // wait until the two processes return
            wait(&status);
            wait(&status);
            // read the number of interactions
            if ( (f_in = fopen(FILE_NAME, "rb")) != NULL ) 
                fread(&num, sizeof(int), 1, f_in);
                printf("Il numero di interazioni è: %d", num);
                fclose(f_in);
            
            return 0;
        
        else 
            // Sono il receiver
            receiver_operation();
        
    
    else 
        // sono il sender
        sender_operation();
    


int readline(int fd, char *str) 
    char c = '\0';
    int i = 0;
    while (c != '\n') 
        read(fd, &c, 1);
        str[i] = c; i++;
    
    str[i] = '\0';
    return i;


void sender_operation() 
    FILE *fin;
    int r_pid, count = 0;
    char stringa[MAX_CHAR+1];
    boolean finito = FALSE;
    signal(SIGUSR1, nothing);

    // aspetto che il receiver scriva sul file il pid e lo apro
    pause();
    if ( (fin = fopen("pid", "rb")) == NULL ) 
        printf("Impossibile aprire file 'pid'.\n");
        return;
    

    // leggo il pid
    fread(&r_pid, sizeof(int), 1, fin);
    fclose(fin);

    while (!finito) 
        // leggo una stringa da tastiera
        kill(0, SIGSTOP);
        printf("Insert a string: ");
        scanf("%s", stringa);

        // controllo se è 'end'
        if ( strcmp(stringa, "end") == 0 ) 
            finito = TRUE;
        

        // scrivo su file
        if ( (fin = fopen("stringa.txt", "w")) == NULL ) 
            printf("Impossibile aprire file 'stringa.txt'.\n");
        
        fprintf(fin, "%s", stringa);
        fclose(fin);

        // segnalo al receiver che il file e' pronto
        kill(r_pid, SIGUSR1);

        // aspetto il risultato
        pause();

        // leggo il risultato
        if ( (fin = fopen("stringa.txt", "r")) == NULL ) 
            printf("Impossibile aprire file 'stringa.txt'.\n");
            return;
        
        fscanf(fin, "%s", stringa);

        // stampo il risultato
        printf("Stringa processata: %s", stringa);
        fclose(fin);

        // incremento numero iterazioni
        count++;
    

    // stampo su un file il numero di iterazioni
    if ( (fin = fopen(FILE_NAME, "wb")) == NULL) 
        printf("Impossibile creare il file %s\n", FILE_NAME);
        return;
    
    fwrite(&count, sizeof(int), 1, fin);
    fclose(fin);
    exit(0);


void receiver_operation() 
    FILE *fout;
    int pid;
    boolean finito = FALSE;
    char stringa[MAX_CHAR+1], result[MAX_CHAR+1];

    signal(SIGUSR1, nothing);

    // scrivo il mio pid su un file
    if ( (fout = fopen("pid", "wb")) == NULL ) 
        printf("Impossibile creare il file 'pid'\n");
        return;
    
    pid = getpid();
    fwrite(&pid, sizeof(int), 1, fout);
    fclose(fout);

    // segnalo il file pronto
    kill(sender_pid, SIGUSR1);

    while (!finito) 
        // ora aspetto che il sender scriva una stringa sul file 'stringa.txt'
        pause();

        // leggo la stringa da processare
        if ( (fout = fopen("stringa.txt", "r")) == NULL ) 
            printf("Impossibile aprire il file 'stringa.txt'\n");
            return;
        
        fscanf(fout, "%s", stringa);
        fclose(fout);

        if ( strcmp(stringa, "end") == 0 ) 
            finito = TRUE;
        

        // processo la stringa
        to_maiusc(stringa, result);

        // scrivo sul file il risultato
        if ( (fout = fopen("stringa.txt", "w")) == NULL ) 
            printf("Impossibile scrivere il risultato su 'stringa.txt'\n");
            return;
        
        fprintf(fout, "%s", result);
        fclose(fout);

        // segnalo il risultato pronto
        kill(sender_pid, SIGUSR1);
    


void to_maiusc(char s[], char* r) 
    int i;
    r = malloc( sizeof(char) * strlen(s) +1);
    // converto la stringa da maiuscola a minuscola
    for(i=0; i<strlen(s); i++) 
        r[i] = toupper(s[i]);
    
    return;

有人知道吗?

【问题讨论】:

【参考方案1】:

让我看看我是否正确,您的问题是子进程无法读取stdin,对吗?你可以使用fscanf(stdin, stringa);

我已经用一个简单的例子进行了测试并且工作了(只是将你的 scanf 更改为 fscanf)。让我知道这是否是您的问题。

【讨论】:

我很高兴地说“你是对的”。这解决了我的问题。有谁知道为什么在这里使用 scanf 会带来问题? 我不是 100% 确定,但这可能与文件描述符有关。当您的子进程使用 scanf 时,它会尝试读取作为管道的标准输入。因此,有必要指定标准输入以避免这种行为。但同样,我只是在猜测。

以上是关于叉子后如何通过键盘在孩子中引入字符串的主要内容,如果未能解决你的问题,请参考以下文章

叉子过程不从管道读取

输入四个字符后如何编写UItextfield长度和更改键盘数字格式的条件

如何更改键盘完成按钮的行为?

输入六个字符后自动隐藏键盘

在python中,应如何捕获用户键盘输入?

python如何n-1个数是小写然后全部转换为小写