学习Operating System的底层机制对于进行底层开发的人员来说很重要,下面这个简单的程序是关于fork process的练习。以下是这个程序的要求说明。
Write a simple C (not C++, C#) program that takes 3 command line
arguments and treats the first 2 like commands and the 3rd as a filename.
Call it q1.c. We shall compile it as follows:
% cc -Wall -o q1 q1.c
Your program would be invoked like this:
% q1 <cmd1> <cmd2> <fileName>
The program should then fork off 2 children. One child should exec
cmd1 and the other cmd2. You can assume that
- <cmd1> takes no input and writes to standard output.
- <cmd2> reads from standard input and writes to standard output
- there may or may not be a file in the current directory
with the passed name <fileName>
When q1 is run with such arguments, it should have the same effect as
giving the command
% <cmd1> | <cmd2> > <fileName>
i.e. the output of the first command is piped to the second and the
output of the second is redirected to the named file.
Use good programming practices throughout. The exit status/return value
of your program should indicate its success/failure.
You will need to use system calls like open, close, write, dup/dup2,
wait/waitpid, pipe, fork and some form of exec...
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, char ** argv)
{
char *filename;
mode_t mode;
int pfd;
int fd[2];
char * strerror(int);
if (argc != 4)
{
printf("Invalid number of arguments\n");
exit(1);
}
/* create a pointer point to the file name */
filename = argv[3];
/* define file access mode */
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
/* open a file */
pfd = open(filename, O_RDWR | O_CREAT | O_EXCL | O_TRUNC, mode);
if (pfd == -1)
{
printf("%s: %s.\n", filename, strerror(errno));
exit(1);
}
/* create a pipe. */
pipe(fd);
switch(fork())
{
case -1:
perror("Bad fork()");
exit(1);
case 0:
/* This child need only the write/in end of the pipe and can close the other end. */
close(fd[0]);

/* redirect standard output to the write/in end of the pipe */
if (dup2(fd[1], STDOUT_FILENO) == -1)
{
perror("dup2() fail");
exit(1);
}
/* now that standard output has been redirected, this file descriptor is no longer needed */
close(fd[1]);
execlp(argv[1], argv[1], NULL);
perror("");
exit(1);
default:
switch(fork())
{
case -1:
perror("Bad fork()");
exit(1);
case 0:
/* This child need only the read/out end of the pipe and can close the other end. */
close(fd[1]);
if (dup2(fd[0], STDIN_FILENO) == -1)
{
perror("dup2() fail");
exit(1);
}
/* now the standard input has been redirected, this file descriptor is no longer needed */
close(fd[0]);
/* redirect standard output to the file */
if (dup2(pfd, STDOUT_FILENO) == -1)
{
perror("dup2() fail");
exit(1);
}
/* now that standard output has been redirected, this file descriptor is no longer neede */
close(pfd);
execlp(argv[2], argv[2], NULL);
perror("");
exit(1);
default:
/* the parent doesn't use the pip */
close(fd[0]);
close(fd[1]);
/* wait for both children to finish */
wait((int *)0);
wait((int *)0);
exit(0);
}
}
return 0;
}


浙公网安备 33010602011771号