具有非阻塞输入和 fork 的 Ncurses
我在使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好的,这是我想到的代码。
OK so here's the code I had in mind.