题目:建立双向管道,实现:父进程向子进程传送一个字符串,子进程对该字符串进行处理(小写字母转为大写字母)后再传回父进程。
实现代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> void TestPipeDouble()
{
pid_t pid;
int fd_A[2], fd_B[2];
if (pipe(fd_A) || pipe(fd_B)) { // 创建管道A和管道B
perror("pipe fail");
return;
}
char szBuf[1024];
pid = fork();
if (pid == 0) {
close(fd_A[1]);
close(fd_B[0]);
printf("Child pid:%d\n", getpid());
while(1) {
memset(szBuf, 0, 1024);
read(fd_A[0], szBuf, 1024);
int i;
for (i = 0; i < strlen(szBuf); ++i) {
if (szBuf[i] <= 'z' && szBuf[i] >= 'a') {
szBuf[i] += ('A' - 'a');
}
}
write(fd_B[1], szBuf, strlen(szBuf));
}
close(fd_A[0]);
close(fd_B[1]);
}
else {
close(fd_A[0]);
close(fd_B[1]);
printf("Father pid:%d\n", getpid());
while(1) {
usleep(1000);
printf("Send:");
scanf("%s", szBuf);
write(fd_A[1], szBuf, strlen(szBuf));
memset(szBuf, 0, 1024);
read(fd_B[0], szBuf, 1024);
printf("Recv:%s\n", szBuf);
}
close(fd_A[1]);
close(fd_B[0]);
} } int main()
{
TestPipeDouble();
return 0;
}
题目:基于管道,并借助于dup2、exec函数族,实现命令“ps -ef | grep pipe”。
实现代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h> // 相当于“ps -ef | grep pipe”
void TestPipeRedir() // 重定向
{
int fd[2];
pid_t pid;
if(pipe(fd) == -1) {
perror("pipe failed");
return;
}
pid = fork();
if (pid == 0) {
dup2(fd[1], STDOUT_FILENO); // 将本应输出至stdout的“ls -l”,转而输出至管道写端
close(fd[0]);
close(fd[1]);
execlp("ps", "ps", "-ef", NULL); // 参数列表以NULL结尾
}
else {
dup2(fd[0], STDIN_FILENO); // grep本应由stdin读入“ls -l”, 转而从管道读端读入
close(fd[0]);
close(fd[1]);
execlp("grep", "grep", "pipe", NULL);
}
} int main()
{
TestPipeRedir();
return 0;
}
题目:使用popen函数实现命令“ps -ef | grep pipe”。
实现代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h> /* 使用sort对数组arr进行排序 */
void TestPipePopen_easy()
{
int arr[] = {2, 3, 7, 3, 5, 10, 9};
FILE *pFile = popen("sort -n", "w"); // 当前进程将arr传入子进程sort
int i;
for (i = 0; i != sizeof(arr) / sizeof(int); i++) {
fprintf(pFile, "%d\n", arr[i]); // 父进程通过pFile来发送数据至子进程
}
pclose(pFile); // 一旦pclose,即开始执行sort命令
} /* 实现命令ps -ef | grep pipe */
void TestPipePopen_complex()
{
FILE *pRead = popen("ps -ef", "r"); // 子进程ps将数据写入当前进程
FILE *pWrite = popen("grep pipe", "w"); // 当前进程将数据写入子进程grep
char szBuf[1024];
while(fgets(szBuf, 1024, pRead)) // 逐行读取
{
fputs(szBuf, pWrite); }
pclose(pRead);
pclose(pWrite);
} int main()
{
TestPipePopen_easy();
TestPipePopen_complex();
return 0;
}
题目:通过命名管道实现任意两个进程间通信(一个进程在读,另一个在写)。
实现代码:
/*
* 命名管道
* 进程间通信————任意两个进程
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <fcntl.h> void ReadFifo(int fd)
{
char szBuf[1024];
while (1) {
memset(szBuf, 0, 1024);
read(fd, szBuf, 1024);
printf("Process[PID:%d] Recv:%s\n", getpid(), szBuf);
if (strcmp(szBuf, "exit") == 0) {
return;
}
}
} void WriteFifo(int fd)
{
char szBuf[1024];
while (1) {
setbuf(stdout, NULL);
printf("Process[PID:%d]Send:", getpid());
scanf("%s", szBuf);
write(fd, szBuf, strlen(szBuf));
if (strcmp("exit", szBuf) == 0) {
return;
}
}
} int main(int argc, char **argv)
{
if (argc != 3) {
printf("usage: %s [r | w] filename\n", argv[0]);
printf("\tr: read the fifo\n");
printf("\tw: write the fifo\n");
printf("\tfilename: the fifo file name\n");
return -1;
}
int fd;
struct stat info;
stat(argv[2], &info);
if (!S_ISFIFO(info.st_mode)) { // 判断是否为管道文件
printf("this file is not fifo\n");
return -1;
}
if (argv[1][0] == 'r') {
fd = open(argv[2], O_RDONLY); // 打开管道文件
if (fd < 0){
perror("open fail");
return -1;
}
ReadFifo(fd);
}
else if (argv[1][0] == 'w') {
fd = open(argv[2], O_WRONLY);
if (fd < 0) {
perror("open fail");
return -1;
}
WriteFifo(fd);
}
close(fd);
return 0;
}