一个典型的Linux C应用程序:允许简单的基于IPC管道的标准I/O端口






4.61/5 (9投票s)
演示如何创建一个简单的应用程序,该应用程序通过终端标准I/O端口进行交互,以提供基于IPC管道的进程间通信
引言
典型的Linux(或UNIX)终端应用程序,如cat命令,提供了三种输入数据的方式
- 通过将文件名作为参数传递:
cat file.txt <enter>
- 通过规范模式输入:
cat <enter>
- 规范模式是一种终端输入模式,以行为单位进行处理。这意味着程序在输入新行(CRLF)或EOF(文件结束)字符后读取信息。
- 通过创建管道连接将数据发送到进程(或从进程接收数据)
cat file.txt | more <enter>
本文演示了如何创建一个小型应用程序(makeupper),该应用程序支持这三种数据输入方式。
注意:源代码应该可以在任何UNIX系统或Linux发行版中无错误地编译。
终端输入/输出
在Linux和所有其他UNIX系统中(如IBM-AIX),从文件读取数据和从终端读取数据,或者将数据写入文件和将数据写入屏幕之间没有区别 - 特别是当数据只包含字符字符串时。
终端提供三个I/O端口
- 标准输入:默认是键盘
- 标准输出:默认是终端屏幕
- 标准错误:默认是终端屏幕
有两种函数集用于处理这些I/O端口
- 低级I/O系统调用:使用文件描述符来访问标准输入、输出和错误。
- 标准I/O库:使用流,实现为指向FILE*结构的指针(
#include <stdio.h>
)。
注意:您可以获取有关低级系统调用的更多信息:read、write、open、select、close。
源代码包含一个名为test.c的小应用程序,它通过将一个string
打印到终端屏幕(标准输出)来演示低级系统调用和标准I/O库函数的使用。源代码是最简单的
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main ( int _argc, char *_argv[] )
{
char *ptr = "This is an output test!\n";
printf( ptr );
fprintf( stdout, ptr );
write( 1, ptr, strlen(ptr) );
return 0;
}
使用C编译器构建test.c
cc -o test test.c
当您执行./test时,将获得以下输出
看到了吗?由ptr指向的字符串"This is an output test!"通过三个不同的函数被打印到屏幕(标准输出)
printf
:标准I/O库的一部分,默认始终将string
打印到标准输出fprintf
:标准I/O库的一部分。注意第一个参数stdout
流将ptr string
重定向到标准输出(或屏幕)。write
:低级系统调用。注意第一个参数1
,它是标准输出的文件描述符。
Makeupper示例
源代码中还有两个示例:makeupper.c和makeupper2.c。它们做的事情相同。区别在于makeupper.c使用低级系统调用,而makeupper2.c使用标准I/O库。
makeupper
示例非常简单。它的目的是将输入数据中的字母转换为大写并打印到标准输出。然而,它演示了如何从标准输入和文件读取。第一个示例makeupper.c使用低级系统调用
/* Makeupper.c */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
int main ( int _argc, char *_argv[] )
{
int fd_main = 0;
char ch = 0;
fd_main = _argc == 1 ? 0 : open(_argv[1], O_RDONLY);
if ( fd_main == -1 )
{
perror("input");
exit(-1);
}
while ( read( fd_main, &ch , 1 ) )
{
ch = toupper(ch);
write( 1, &ch, 1 );
}
close(fd_main);
return 0;
}
注意该行
fd_main = _argc == 1 ? 0 : open(_argv[1], O_RDONLY);
如果没有传递文件路径参数,则fd_main
假定为标准输入描述符。当传递文件作为参数时,使用open
系统调用来打开文件。
makeupper2.c使用标准I/O库函数而不是系统调用
/* Makeupper2.c */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main ( int _argc, char *_argv[] )
{
FILE *f_file = NULL;
char ch = 0;
f_file = _argc == 1 ? stdin : fopen(_argv[1], "r");
if ( f_file == NULL )
{
perror("input");
exit(-1);
}
while ( !feof(f_file) )
if ( (ch = fgetc(f_file)) > 0 )
fputc( toupper(ch), stdout );
fclose(f_file);
return 0;
}
构建两个示例
-
cc -o makeupper makeupper.c
-
cc -o makeupper2 makeupper2.c
通过不带参数执行./makeupper(或./makeupper2),它将在规范模式下启动。按下回车后,makeupper
会接收该行。要退出规范模式,您应该按CTRL+D或CTRL+\
您也可以传递一个文件路径
或者makeupper可以从进程的标准输入接收输出
重定向I/O
您可以将标准输出和错误重定向到文件或设备(/dev/...)。为了说明这一点,请键入并编译以下代码(您可以将其命名为test2.c)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ( int _argc, char *_argv[] )
{
char *p1 = "printed to standard output via stdlib.\n";
char *p2 = "printed to standard error via stdlib.\n";
char *p3 = "printed to standard output via low-level calls.\n";
char *p4 = "printed to standard error low-level calls.\n";
fprintf( stdout, p1 );
fprintf( stderr, p2 );
write ( 1, p3, strlen(p3) );
write ( 2, p4, strlen(p4) );
return 0;
}
有四个指针指向四个字符串。p1
和 p3
被打印到标准输出,而p2
和p4
被打印到标准错误。
构建它
cc -o test2 test.c
通过执行./test2,我们得到
- ./test2 - 您将所有字符串打印到屏幕。
- ./test2 >file.txt - 将标准输出重定向到file.txt。注意只有
p1
和p3
字符串保存在file.txt中。 - ./test2 2>file.txt 将标准错误重定向到file.txt。注意只有
p2
和p4
字符串保存在file.txt中。 - ./test2 >file.txt 2>&1 将输出和错误都重定向到file.txt。注意技巧2>&1(表示将标准错误重定向到标准输出)。
如果您想追加到现有文件:./test2 >>file.txt 或./test2 >>file.txt 2>&1。
希望这有所帮助。
历史
- 2008年10月14日:第一个版本