具有非阻塞输入和 fork 的 Ncurses

发布于 2024-11-16 21:37:48 字数 5004 浏览 4 评论 0原文

我在使用 fork() 和 ncurses 的进程之间进行正确的读写时遇到问题。我有一个控制应用程序输入的进程(让我称之为儿子),而且我还有一个控制应用程序逻辑的进程(父进程)。

我的问题是我在管道内写入以将信息从儿子发送到父母,但父母没有读取任何内容。

由于非阻塞性质,我添加了等待和信号以在读写时相互排除进程。

让我向您展示一些代码:)

    //---- pipes, read i write no bloquejants ---------
    int flags_f0 = fcntl(pip_fill[0],F_GETFL);
    int flags_f1 = fcntl(pip_fill[1],F_GETFL);
    int flags_p0 = fcntl(pip_pare[0],F_GETFL);
    int flags_p1 = fcntl(pip_pare[1],F_GETFL);
    int flags_read = fcntl(0,F_GETFL);
    int flags_write = fcntl(1,F_GETFL);


    fcntl(pip_fill[0],F_SETFL,flags_f0 | O_NONBLOCK);
    fcntl(pip_fill[1],F_SETFL,flags_f1 | O_NONBLOCK);
    fcntl(pip_pare[0],F_SETFL,flags_p0 | O_NONBLOCK);
    fcntl(pip_pare[1],F_SETFL,flags_p1 | O_NONBLOCK);
    fcntl(0,F_SETFL,flags_read | O_NONBLOCK);
    fcntl(1,F_SETFL,flags_write | O_NONBLOCK);
    //-------------------------------------------------

    //---- semàfors ----
    int id_Sem;

    id_Sem = shmget (IPC_PRIVATE, sizeof(int), IPC_CREAT | 0600);
    if (id_Sem == -1)
    {
        write(2,"Error!\n",7);
        Sortir(&ll_a_r,&ll_res,&ll_mis,&ll_n_mis,&c,&c_write);
        exit (0);
    }


if(SEM_constructor(&sem1) < 0)
{
       shmctl(id_Sem, IPC_RMID, NULL);
    }

    if(SEM_constructor(&sem2) < 0)
{
        shmctl(id_Sem, IPC_RMID, NULL);
        SEM_destructor (&sem1);
    }

    SEM_init (&sem1, 0);
    SEM_init (&sem2, 0);

//------------------



//la primera vegada que entri en el fill posarem les següents dades a la var valor

Afegir_Cadena(&c,"M0:");    //on M0: menú principal

pantalla(w);
pinta_menu_principal(w,a_menus);    //pinta el menú principal per pantalla

pid = fork();

switch (pid)
{
    case -1: //ERROR
        write(2,"Error!\n",7);
        Sortir(&ll_a_r,&ll_res,&ll_mis,&ll_n_mis,&c,&c_write);
        exit(-1);
            break;

    case 0: //FILL
        close(pip_fill[0]); //tanquem l'extrem de la pipe que no usem (la de lectura)
        close(pip_pare[1]); //tanquem l'extrem de la pipe que no usem (la d'escriptura)

        while(1)
        {
                cc = getch();
                if(cc != ERR)
            {
                if(cc == 0x0A)
                {
                    printf("Enter [%s]\n", Retorna_Cad(&c_write));
                    SEM_wait (&sem1);
                    tmp = write(pip_fill[1],Retorna_Cad(&c_write),Retorna_Longitud(&c_write) + 1);  //el fill escriu a la pipe la variable c
                    SEM_signal (&sem1);                                                     //longitud + 1: el +1 es per el \0
                    //printf("Ret: %d",tmp);
                    Esborra_Cadena(&c_write);
                    actualitza_pantalla(w);
                }
                else
                {
                    Afegir_Caracter(&c_write,cc);
                    cc = ERR;
                }
            }

    //***** READ PARE *********
            SEM_wait (&sem2);
            nbytes = read(pip_pare[0],valor,256); //el fill llegeix de la pipe la var un cop ha estat tractada per el pare
            SEM_signal (&sem2);

            if (nbytes > -1)
            {   
                Inserir_Cad(&c,valor);
                //tractar el missatge del pare
        Tractar_Missatge_del_Pare(&ll_mis,&ll_res,&c,w,a_menus,&ll_a_r);
            }
        }
        break;

    default: //PARE
        close(pip_fill[1]); //tanquem l'extrem de la pipe que no usem (la d'escriptura)
        close(pip_pare[0]); //tanquem l'extrem de la pipe que no usem (la de lectura)

        while(1)
        {
            temps_inici = (float)clock();
            SEM_wait (&sem1);
            nbytes = read(pip_fill[0],valor,256);//el pare llegeix de la pipe la var c 
            SEM_signal (&sem1);

            if (nbytes > -1 || tmp > 0)
            {   //vol dir que hem llegit algo per la pipe pip_fill
                tmp++;
                Inserir_Cad(&c,valor);
                Tractar_Missatge_del_Fill (&ll_mis,&c,&ll_n_mis,w);
                SEM_wait (&sem2);
                   write(pip_pare[1],Retorna_Cad(&c),Retorna_Longitud(&c) + 1); //el pare escriu a la pipe la var tractada
                SEM_signal (&sem2);

                actualitza_pantalla(w);
            }


            temps_final = (float)clock();
            temps_per_bucle = (float)(temps_final - temps_inici) / (float)CLOCKS_PER_SEC;

            Esborra_Cadena(&aux);
            Afegir_Float (&aux, temps_per_bucle);
            //mvwprintw(w[4],8,1,Retorna_Cad(&aux));

        }
        break;
    }
}
else
    {
    exit(1);    //login incorrecte --> sortim de l'aplicacio
}

我没有发布所有代码,只发布了通过等待和信号完成读+写的主要部分。

也许我正在失去一些我现在看不到的东西。事实上,儿子将在“pipe_fill”上写入,父级将从该管道中读取,同样,父级将在“pipe_pare”上写入,然后儿子将从中读取以发送信息。

我还使用 ncurses 来绘制所有窗口。

感谢您的帮助 :)

I am having problems to make a proper read-write between process with fork() and ncurses. I have a process (let me call it son) that control the input on the application, and also i have a process (the parent) that control the logic of the app.

My problem is that i write inside the pipe to send information from son to parent but parent doesn't read anything.

Due to non-blocking nature, i added waits and signals to mutualy exclude process while read and write.

Let me show you some code :)

    //---- pipes, read i write no bloquejants ---------
    int flags_f0 = fcntl(pip_fill[0],F_GETFL);
    int flags_f1 = fcntl(pip_fill[1],F_GETFL);
    int flags_p0 = fcntl(pip_pare[0],F_GETFL);
    int flags_p1 = fcntl(pip_pare[1],F_GETFL);
    int flags_read = fcntl(0,F_GETFL);
    int flags_write = fcntl(1,F_GETFL);


    fcntl(pip_fill[0],F_SETFL,flags_f0 | O_NONBLOCK);
    fcntl(pip_fill[1],F_SETFL,flags_f1 | O_NONBLOCK);
    fcntl(pip_pare[0],F_SETFL,flags_p0 | O_NONBLOCK);
    fcntl(pip_pare[1],F_SETFL,flags_p1 | O_NONBLOCK);
    fcntl(0,F_SETFL,flags_read | O_NONBLOCK);
    fcntl(1,F_SETFL,flags_write | O_NONBLOCK);
    //-------------------------------------------------

    //---- semàfors ----
    int id_Sem;

    id_Sem = shmget (IPC_PRIVATE, sizeof(int), IPC_CREAT | 0600);
    if (id_Sem == -1)
    {
        write(2,"Error!\n",7);
        Sortir(&ll_a_r,&ll_res,&ll_mis,&ll_n_mis,&c,&c_write);
        exit (0);
    }


if(SEM_constructor(&sem1) < 0)
{
       shmctl(id_Sem, IPC_RMID, NULL);
    }

    if(SEM_constructor(&sem2) < 0)
{
        shmctl(id_Sem, IPC_RMID, NULL);
        SEM_destructor (&sem1);
    }

    SEM_init (&sem1, 0);
    SEM_init (&sem2, 0);

//------------------



//la primera vegada que entri en el fill posarem les següents dades a la var valor

Afegir_Cadena(&c,"M0:");    //on M0: menú principal

pantalla(w);
pinta_menu_principal(w,a_menus);    //pinta el menú principal per pantalla

pid = fork();

switch (pid)
{
    case -1: //ERROR
        write(2,"Error!\n",7);
        Sortir(&ll_a_r,&ll_res,&ll_mis,&ll_n_mis,&c,&c_write);
        exit(-1);
            break;

    case 0: //FILL
        close(pip_fill[0]); //tanquem l'extrem de la pipe que no usem (la de lectura)
        close(pip_pare[1]); //tanquem l'extrem de la pipe que no usem (la d'escriptura)

        while(1)
        {
                cc = getch();
                if(cc != ERR)
            {
                if(cc == 0x0A)
                {
                    printf("Enter [%s]\n", Retorna_Cad(&c_write));
                    SEM_wait (&sem1);
                    tmp = write(pip_fill[1],Retorna_Cad(&c_write),Retorna_Longitud(&c_write) + 1);  //el fill escriu a la pipe la variable c
                    SEM_signal (&sem1);                                                     //longitud + 1: el +1 es per el \0
                    //printf("Ret: %d",tmp);
                    Esborra_Cadena(&c_write);
                    actualitza_pantalla(w);
                }
                else
                {
                    Afegir_Caracter(&c_write,cc);
                    cc = ERR;
                }
            }

    //***** READ PARE *********
            SEM_wait (&sem2);
            nbytes = read(pip_pare[0],valor,256); //el fill llegeix de la pipe la var un cop ha estat tractada per el pare
            SEM_signal (&sem2);

            if (nbytes > -1)
            {   
                Inserir_Cad(&c,valor);
                //tractar el missatge del pare
        Tractar_Missatge_del_Pare(&ll_mis,&ll_res,&c,w,a_menus,&ll_a_r);
            }
        }
        break;

    default: //PARE
        close(pip_fill[1]); //tanquem l'extrem de la pipe que no usem (la d'escriptura)
        close(pip_pare[0]); //tanquem l'extrem de la pipe que no usem (la de lectura)

        while(1)
        {
            temps_inici = (float)clock();
            SEM_wait (&sem1);
            nbytes = read(pip_fill[0],valor,256);//el pare llegeix de la pipe la var c 
            SEM_signal (&sem1);

            if (nbytes > -1 || tmp > 0)
            {   //vol dir que hem llegit algo per la pipe pip_fill
                tmp++;
                Inserir_Cad(&c,valor);
                Tractar_Missatge_del_Fill (&ll_mis,&c,&ll_n_mis,w);
                SEM_wait (&sem2);
                   write(pip_pare[1],Retorna_Cad(&c),Retorna_Longitud(&c) + 1); //el pare escriu a la pipe la var tractada
                SEM_signal (&sem2);

                actualitza_pantalla(w);
            }


            temps_final = (float)clock();
            temps_per_bucle = (float)(temps_final - temps_inici) / (float)CLOCKS_PER_SEC;

            Esborra_Cadena(&aux);
            Afegir_Float (&aux, temps_per_bucle);
            //mvwprintw(w[4],8,1,Retorna_Cad(&aux));

        }
        break;
    }
}
else
    {
    exit(1);    //login incorrecte --> sortim de l'aplicacio
}

I didn't post all the code, only the main part where read+writes are done with waits and signals.

Maybe i am losing something that i can't see right now. The fact is that son will write on 'pipe_fill' and parent will read from this pipe, also, parent will write on 'pipe_pare' and then, son will read from it to send information.

Also i am using ncurses to make all the window drawing.

Thanks for your help :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

太傻旳人生 2024-11-23 21:37:48

好的,这是我想到的代码。

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

int main ()
{
  int pipePC[2];
  int pipeCP[2];

  pipe(pipePC);
  pipe(pipeCP);

  char buf[11];
  int n;

  switch (fork()) {
  case -1:
    exit (1);
    break;
  case 0: /* child */
    close(pipePC[1]);
    close(pipeCP[0]);
    while (1) { /* read, then write */
        n = read(pipePC[0], buf, 10); /* read the question */
        if (n > 0) {
            buf[n] = 0;
            printf ("child got '%s'\n", buf); /* calculate the answer here */
            write(pipeCP[1], "foobar", 6); /* write the answer */
        }
        else {
            printf ("child got nothing\n");
            exit (1);
        }
        sleep(2); /* only to slow down the output */
    }
    break;
  default: /* parent */
    close(pipePC[0]);
    close(pipeCP[1]);
    while (1) { /* write, then read */
        write(pipePC[1], "barfoo", 6); /* ask a question */
        n = read(pipeCP[0], buf, 10); /* get the answer */
        if (n > 0) {
            buf[n] = 0;
            printf ("parent got '%s'\n", buf);
        }
        else {
            printf ("parent got nothing\n");
            exit (1);
        }
        sleep(3); /* only to slow down the output */
    }
    break;
  }
}

OK so here's the code I had in mind.

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

int main ()
{
  int pipePC[2];
  int pipeCP[2];

  pipe(pipePC);
  pipe(pipeCP);

  char buf[11];
  int n;

  switch (fork()) {
  case -1:
    exit (1);
    break;
  case 0: /* child */
    close(pipePC[1]);
    close(pipeCP[0]);
    while (1) { /* read, then write */
        n = read(pipePC[0], buf, 10); /* read the question */
        if (n > 0) {
            buf[n] = 0;
            printf ("child got '%s'\n", buf); /* calculate the answer here */
            write(pipeCP[1], "foobar", 6); /* write the answer */
        }
        else {
            printf ("child got nothing\n");
            exit (1);
        }
        sleep(2); /* only to slow down the output */
    }
    break;
  default: /* parent */
    close(pipePC[0]);
    close(pipeCP[1]);
    while (1) { /* write, then read */
        write(pipePC[1], "barfoo", 6); /* ask a question */
        n = read(pipeCP[0], buf, 10); /* get the answer */
        if (n > 0) {
            buf[n] = 0;
            printf ("parent got '%s'\n", buf);
        }
        else {
            printf ("parent got nothing\n");
            exit (1);
        }
        sleep(3); /* only to slow down the output */
    }
    break;
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文