计算器linuxbc(计算器管道进程嘉言懿行客户端)「计算器 linux」

一、背景初次接触服务器与客户端的知识,先从最简单的做起:了解Linux中使用的计算器
linux中使用的计算器是最为简单的服务器与客户端协同工作的例子
二、从管道到服务器与客户端之前详细的解释过管道的工作原理,但传统的Unix管道只是单方向的传送数据
打个比方,在linux命令行下使用cat /etc/passwd | grep Jack命令
这个命令将cat的输出结果通过管道传送到grep命令的标准输入中
但这只是一个单向的数据传送,grep的输出结果并不会进行回传
而若有两个进程A、B,他们两个协同进行工作,A进程将其输出结果传送给B进程,B进程处理数据完毕后再返回给A进程
这样,它们之间并不是单向的管道,而是一个双向的管道
B对A提供服务,而A是B的客户
A就叫做客户端,B叫做服务器
三、bc与dc打开我们的linux命令行终端,输入bc命令调用linux的计算器,写入2+2
使用enter键则会返回结果
这时候大家可能会觉得我们向bc进程输入了数据,bc进行运算后将结果返回给了屏幕终端
而实际上并非如此
实际上bc只是一个用户的界面,让用户输入数值与给用户返回结果而已
这个可以使用man bc命令来查看
上面简介说bc是一个计算器语言
而看以下dc的手册
这里可以看到,dc是一个计算器
什么意思呢?其实是说,这里的bc只是一个界面,而dc才是真正数据进行计算的地方
bc将接收到的数据传送给dc进行运算,运算结束后,dc将结果返回给bc显示输出
那么,也就是说,bc其实一个客户端,而dc是一个服务器
四、编写bc搞清楚了bc与dc之间的关系,那么,我们就可以使用现有的知识编写出自己的bc
当然,这里的bc指的是用户的交互界面
而后台的计算还是要交给dc
#include<stdio.h>#include<sys/types.h>#include<sys/wait.h>#include<stdlib.h>#include<unistd.h>#define oops(m,x) {perror(m);exit(x);}void be_bc(int ,int );void be_dc(int ,int );void fatal(char );int main(){int pid,todc[2],fromdc[2];if(pipe(todc) == -1 || pipe(fromdc) == -1)oops(\"pipe failed\",1);if((pid = fork()) == -1)oops(\"fork failed\",2);if(pid == 0)be_dc(todc,fromdc);else{be_bc(todc,fromdc);wait(NULL);}}void be_bc(int todc[2],int fromdc[2]){int num1,num2;char operation[BUFSIZ],message[BUFSIZ],fgets();FILE fpout,fpin,fdopen();close(todc[0]);close(fromdc[1]);fpout = fdopen(todc[1],\"w\");fpin = fdopen(fromdc[0],\"r\");if(fpout == NULL || fpin == NULL)fatal(\"Error convering pipes to streams\");while(printf(\"tinybc:\"),fgets(message,BUFSIZ,stdin) != NULL){if(sscanf(message,\"%d%[-+/^]%d\",&num1,operation,&num2) != 3){printf(\"syntax error\n\");continue;}if(fprintf(fpout,\"%d\n%d\n%c\np\n\",num1,num2,operation) == EOF)fatal(\"Error writing\");fflush(fpout);if(fgets(message,BUFSIZ,fpin) == NULL)break;printf(\"%d %c %d = %s\",num1,operation,num2,message);}fclose(fpout);fclose(fpin);}void be_dc(int in[2],int out[2]){if(dup2(in[0],0) == -1)oops(\"dc:cannot redirect stdin\",3);if(dup2(out[1],1) == -1)oops(\"dc:cannot redirect stdout\",4);close(in[1]);close(out[0]);close(in[0]);close(out[1]);execlp(\"dc\",\"dc\",NULL);oops(\"cannot run dc\",5);}void fatal(char mess){fprintf(stderr,\"fatal:%s\n\",mess);exit(1);}此程序的实现原理很简单,只是使用了管道方面的系统调用然后进行重定向
将父程序的输出输入到dc中,将dc的输出输入到父进程中就行了
运行结果如下:在这里,我们一定要清楚哪些数据是dc通过管道传递给bc的
五、总结在这里简单的阐述了一下何为服务器与客户端
并且通过一个实际的例子:linux中的计算器来具体的了解了一下协同进程的工作方式
最后编写了一段bc交互程序代码来了解bc是如何与dc进行数据的传递的
计算器linuxbc(计算器管道进程嘉言懿行客户端)
(图片来源网络,侵删)

联系我们

在线咨询:点击这里给我发消息