I wanted to do this problem but I cannot take input message:
Create a program that does the following:
1.Create a parent and a child process
2.The parent process reads a number from keyboard and sends it to the child
3.The child calculates if the given number is prime or not and prints the result on screen
This is my code:
#include <iostream>
#include <unistd.h> // for fork()
#include <string.h> // for strerror()
#include <sys/wait.h>
#include <sys/types.h>
using namespace std;
bool isprime(int number);
int main()
{
int num;
pid_t pid;
int fd[2];
char buffer[100];
pipe(fd);
pid = fork();
//parent process
if (pid > 0)
{
cin>>num;
write(fd[1], &num, sizeof(num));
close(fd[1]);
int status;
//Do not check for errors here
wait(&status);
}
//child process
else if (pid == 0)
{
read(fd[0], buffer, 100);
close(fd[0]);
if (isprime(num))
{
cout<<"number is prime";
}
else
{
cout<<"number is not prime";
}
return EXIT_SUCCESS;
}
else
{
cout << "fork() failed (" << strerror(errno) << ")" << endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
bool isprime(int number)
{
if (number < 2)
return false;
if (number == 2)
return true;
for (int i = 2; (i*i) <= number; i++)
{
// Take the rest of the division
if ((number % i) == 0)
return false;
}
return true;
}
this my result of run
Using a pipe along with fork is not that hard, but you must respect some rules:
each part should close the handle that it does not use. Not doing it is a key for future problems
starting from the fork, changes in one process are not reflected in the other one
Your code should become:
...
//parent process
if (pid > 0)
{
close(fd[0]); // close the part that only the other process will use
cin>>num;
write(fd[1], &num, sizeof(num));
close(fd[1]);
int status;
//Do not check for errors here
wait(&status);
}
//child process
else if (pid == 0)
{
close(fd[1]); // close the part used by the other process
read(fd[0], &num, sizeof(num)); // read into num what the parent has written
close(fd[0]);
...
In real world code, you should check that every read is successfull (both from cin and from the pipe...)
Related
I am trying to pipe data from one child process to another. When I run this, it hangs. If I don't make it wait for the first child process, it goes back to the top of the loop prompting for commands without giving the expected output, and when I prompt it to quit, it dumps all of the output I was expecting. I had it working with just one child process, but then the second execvp killed the parent process, and I didn't get back to the top of the loop prompting for more commands.
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>
using namespace std;
int main(int argc, const char * argv[]) {
bool quit=0;
char quitArray[] = "quit";
int pipeReturnValue, fork1ReturnValue, fork2ReturnValue, pipefd[2], checkForQuit;
//Enter a loop where each iteration prompts for two single-line inputs
while (!quit) {
//Get command 1
char command1[128];
printf("Enter command 1: ");
fgets(command1,128,stdin);
command1[strlen(command1) -1] = 0;
//Exit if user enters quit
checkForQuit = strncmp(command1, quitArray, 4);
if (checkForQuit == 0) {
exit(0);
}
//Get command 2
char command2[128];
printf("Enter command 2: ");
fgets(command2,128,stdin);
command2[strlen(command2) -1] = 0;
//Exit if user enters quit
checkForQuit = strncmp(command2, quitArray, 4);
if (checkForQuit == 0) {
exit(0);
}
//Open pipe
pipeReturnValue = pipe(pipefd);
if (pipeReturnValue < 0) {
perror("Pipe failed");
exit(1);
}
//Fork 1
fork1ReturnValue = fork();
if(fork1ReturnValue < 0) {
perror("Fork failed");
exit(1);
}
else if (fork1ReturnValue == 0) {
//Fork 2
fork2ReturnValue = fork();
if (fork2ReturnValue < 0) {
perror("Fork 2 failed");
}
else if (fork2ReturnValue == 0) {
//close read end of pipe
close(pipefd[0]);
//parse command 1 arguments
//store tokens in array
char *arguments[6] = {};
arguments[0] = strtok(command1, " ");
int tokenCounter = 0;
while (arguments[tokenCounter] != NULL) {
tokenCounter++;
arguments[tokenCounter] = strtok(NULL, " ");
}
//dup stdo to pipe
dup2(pipefd[1], 1);
//execute arguments
execvp(arguments[0], arguments);
}
else {
wait(&fork2ReturnValue);
//close write end of pipe
close(pipefd[1]);
//parse command 2 arguments
//store tokens in array
char *arguments[6] = {};
arguments[0] = strtok(command2, " ");
int tokenCounter = 0;
while (arguments[tokenCounter] != NULL) {
tokenCounter++;
arguments[tokenCounter] = strtok(NULL, " ");
}
//dup stdin to pipe
dup2(pipefd[0], 0);
//exec
execvp(arguments[0], arguments);
}
}
else {
wait(&fork1ReturnValue);
}
}
return 0;
}
I finally figured it out. I needed to open the pipe after the first fork rather than before.
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>
using namespace std;
int main(int argc, const char * argv[]) {
bool quit=0;
char command1[128],
command2[128],
quitArray[] = "quit";
int pipeReturnValue,
fork1ReturnValue,
fork2ReturnValue,
checkForQuit,
pipefd[2];
//Loop where each iteration prompts for two single-line inputs
while (!quit) {
//Get command 1
printf("Enter command 1: ");
fgets(command1,128,stdin);
command1[strlen(command1) -1] = 0;
//Exit if user enters quit
checkForQuit = strncmp(command1, quitArray, 4);
if (checkForQuit == 0) {
quit = 1;
exit(0);
}
//Get command 2 and trim trailing new line character
printf("Enter command 2: ");
fgets(command2,128,stdin);
command2[strlen(command2) -1] = 0;
//Exit if user enters quit
checkForQuit = strncmp(command2, quitArray, 4);
if (checkForQuit == 0) {
quit = 1;
exit(0);
}
//Fork to create 1st child process, return error if fork fails
fork1ReturnValue = fork();
if(fork1ReturnValue < 0) {
perror("Fork 1 failed");
exit(1);
}
//Open pipe, return error if fork fails
pipeReturnValue = pipe(pipefd);
if (pipeReturnValue < 0) {
perror("Pipe failed");
exit(1);
}
//First child process
else if (fork1ReturnValue == 0) {
//Fork to create 2nd child process, return error if fork fails
fork2ReturnValue = fork();
if (fork2ReturnValue < 0) {
perror("Fork 2 failed");
}
//Second child process
else if (fork2ReturnValue == 0) {
//close read end of pipe
close(pipefd[0]);
//Parse command 1 arguments, store tokens in an array
char *arguments[6] = {};
arguments[0] = strtok(command1, " ");
int tokenCounter = 0;
while (arguments[tokenCounter] != NULL) {
tokenCounter++;
arguments[tokenCounter] = strtok(NULL, " ");
}
//Dup standard output to write side of pipe
dup2(pipefd[1], 1);
//Execute arguments from command 1
execvp(arguments[0], arguments);
}
//First child code continued
else {
//Wait for child 2 to to terminate
wait(&fork2ReturnValue);
//Close write end of pipe
close(pipefd[1]);
//Parse command 2 arguments, store tokens in array
char *arguments[6] = {};
arguments[0] = strtok(command2, " ");
int tokenCounter = 0;
while (arguments[tokenCounter] != NULL) {
tokenCounter++;
arguments[tokenCounter] = strtok(NULL, " ");
}
//dup standard input to read side of pipe
dup2(pipefd[0], 0);
//Execute arguments from command 2
execvp(arguments[0], arguments);
}
}
//Parent process continued
else {
//Wait for child 1 to terminate
wait(&fork1ReturnValue);
}
//return to top of loop
}
return 0;
}
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <sys/utsname.h>
#include <unistd.h>
using namespace std;
//first comannd to execute
void first(int pipeA[], char * command[]){
//redirect STDOUT to pipe[1] and close the pipe[0] we are not using
dup2(pipeA[1], 1);
close(pipeA[0]);
execvp(command[0], command);
printf(" first error ");
exit(127);
}
void second(int pipeA[], char * command2[]){
//redirect STDIN to pipe[0] and close the pipe[1] that we are not using
dup2(pipeA[0], 0);
close(pipeA[1]);
//This doesnt seem to be doing anything at times
execvp(command2[0], command2);
perror(" second error ");
exit(127);
}
int main(void)
{
char buf[1024];
char * command[1024];// this one is the first input usually 'cat file.txt'
//Use only one or the other, sort never works and 'grep U' works sometimes
char * command2[] = {(char *)"sort", (char *) NULL};// this is wants to sort the above 'command[1024]' and its use in the second function
//char * command2[] = {(char *)"grep",(char *)"U",(char *) NULL};// this is wants to grep the above 'command[1024]' and its use in the second function
//variables for forks and waits
pid_t pid;
pid_t pid2;
int status;
int status2;
//see if || exists not in use currently
bool pipeExists = false;
//create pipe
int pipeA[2];
pipe(pipeA);
//first line and ask for input,
cout<< "command: ";
while (fgets(buf,1024,stdin) != NULL)
{
buf[strlen(buf) -1] = 0;
//Save input into buf and tokenized? it
//NOT YET CATCHING ||, im only debugging and usually use use 'cat file.txt'
int number =0;
char * ptr;
ptr = strtok(buf, " ");
while(ptr != NULL){
command[number] = ptr;
ptr = strtok(NULL, " ");
number++;
}
//***************************************************************
//1. do the pipes go here or after the children?
//They seem to be working here but im not really sure where they should be
close(pipeA[0]);
close(pipeA[1]);
//create first child
if ((pid = fork()) <0)
printf("fork error");
else if (pid == 0)
{ /* child */
//create second child INSIDE ORIGINAL CHILD
//2. Is this correct? or is there not supposed to be grandchildren?
if ((pid2 = fork()) <0)
printf("fork 2 error");
else if (pid == 0)
{ /* child */
second(pipeA, command2);
printf("couldn't execute: %s");
exit(127);
}
//first command from buf
first(pipeA, command);
printf("couldn't execute: %s");
exit(127);
//3. Do I wait for this child aswell?
if ( (pid2 = waitpid(pid2, &status2, 0)) < 0)
printf("waitpid error");
}
/* parent */
if ( (pid = waitpid(pid, &status, 0)) < 0)
printf("waitpid error");
printf("Command :");
//***************************************************************
//***************************************************************
//SECOND WAY OF DOING IT
// THIS WAY IT TRIGGERS WAITPID ERRORS.
/*
close(pipeA[0]);
close(pipeA[1]);
//create first child
if ((pid = fork()) <0)
printf("fork error");
else if (pid == 0)
{
first(pipeA, command);
printf("couldn't execute: %s");
exit(127);
}
//create second child INSIDE ORIGINAL CHILD
if ((pid2 = fork()) <0)
printf("fork 2 error");
else if (pid == 0)
{
second(pipeA, command2);
printf("couldn't execute: %s");
exit(127);
}
//3. Do I wait for this child aswell?
if ( (pid2 = waitpid(pid2, &status2, 0)) < 0)
printf("waitpid error");
if ( (pid = waitpid(pid, &status, 0)) < 0)
printf("waitpid error");
printf("Command :");
*/
//***************************************************************
}
exit(0);
}
Pretty much what the code shows here with its questions.
I need to create a microshell that takes in a command ("cat file.txt") and execute it with execvp() and pipe it to another process and either "sort" or "grep U" or anyother.
It's just that my processes won't run correctly at time or wont display anything. I have closed pipes all over the place and nothing has happen.
Solution by OP.
This is the code that works for microshell.
I ended up with creating two processes in the original parents process.
Moving some variables inside the while loop and resetting them to work again. Also create the pipe everytime the code runs and close the pipes.
Created a waitpid() for both processes not just one.
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <sys/utsname.h>
#include <unistd.h>
using namespace std;
//This function will execute the users first command.
//It takes in a pipe the command array and a boolean to check for piping
//If a pipe exists then the boolean is true and will dup() the STDOUT into the write part of the pipe
//We close unecessary parts of the pipe and execvp() the command in the command array
//there it some error checkink in case the command doesn't execute
void first_command(int pipeA[], char * command[], bool pipeExists){
if(pipeExists){
dup2(pipeA[1], 1);
close(pipeA[0]);
}
execvp(command[0], command);
printf("can not execute first command. \n");
exit(127);
}
//This function is only called in the main is a piping exists
//It takes in a pipe and a command array
//It dup() the STDIN from the read end of the pipe and closes the unsued end
//It will execute the command accorind to what was provided in the the pipe
void second_command(int pipeA[], char * command2[]){
dup2(pipeA[0], 0);
close(pipeA[1]);
execvp(command2[0], command2);
printf("can not execute second command. \n");
exit(127);
}
int main(void)
{
//this variable will take in the line of input submitted by the user
char buf[1024];
//PIDs for the two child processes
pid_t pid;
pid_t pid2;
//these will be use to check the status of each child in the parent process
int status;
int status2;
//initializes the pipe
int pipeA[2];
//out put the first line to ask user for input
cout<< "480shel> ";
//stay inside the loop and keep asking the user for input until the user quits the program
while (fgets(buf,1024,stdin) != NULL){
//initialize a boolean to check if user wants to pipe something, set to false by default until we check with user
bool pipeExists = false;
//initialize this arrays to NULL so anything that store in them gets cleared out.
//these arrays will hold the commands that the user wants to carry out.
char * command[1024] = {NULL, NULL, NULL};
char * command2[1024] = {NULL, NULL, NULL};
//Important to delete mark the last byte as 0 in our input
buf[strlen(buf) -1] = 0;
//initialize this number to zero to start save the tokens at this index
int index = 0;
//a char * to hold the token saved by strtok
char * ptr;
ptr = strtok(buf, " ");
//Loop through 'buf' and save tokens accordingly
while(ptr != NULL){
//If ptr is equal to q or quit then user want to exit program
if(strcmp( ptr, "q" ) == 0){
exit(0);
}
if(strcmp( ptr, "quit" ) == 0){
exit(0);
}
//if ptr is equal to || user wants to pipe something and we change pipeExists to true
if(strcmp( ptr, "||" ) == 0){
pipeExists = true;
index= 0;
ptr = strtok(NULL, " ");
}
//enter here while user doesnt want to user pipes
if(!pipeExists){
command[index] = ptr;
ptr = strtok(NULL, " ");
index++;
}
//enter here if user want to use pipes
if(pipeExists){
command2[index] = ptr;
ptr = strtok(NULL, " ");
index++;
}
}
//if pipes exists then initialize it
if(pipeExists){
pipe(pipeA);
}
//create first child
if ((pid = fork()) == 0) {
//pass in the pipe, commands and pipe to function to execute
first_command(pipeA, command, pipeExists);
}
else if(pid < 0){
//error with child
cerr<<"error forking first child"<<endl;
}
// if pipe exists create a second process to execute the second part of the command
if(pipeExists){
//create second child
if ((pid2 = fork()) == 0) {
second_command(pipeA, command2);
}
else if(pid2 < 0){
//error with second child
cerr<<"error forking second child"<<endl;
}
}
//if the pipe was created then we close its ends
if(pipeExists){
close(pipeA[0]);
close(pipeA[1]);
}
//wait for the first child that ALWAYS executes
if ( (pid = waitpid(pid, &status, 0)) < 0)
cerr<<"error waiting for first child"<<endl;
//wait for the second child bu only if user wanted to created to use piping
if(pipeExists){
if ( (pid2 = waitpid(pid2, &status2, 0)) < 0)
cerr<<"error waiting for second child"<<endl;
}
cerr<<"480shell> ";
}//endwhile
exit(0);
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
Im trying to create two children for each process(binary tree) and if n=3 the process tree structure should be like (1)->(2),(1)->(3),(2)->(4),(2)->(5).I have written a program where in i am able to create 2 processes for a prent process and 2 process for each child process but I want to provide a number n=number and create the processes based on the number passed in binary Tree format.
Here is my code:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
int foo(const char *whoami) {
printf("I am a %s. My pid is:%d my ppid is %d\n", whoami, getpid(), getppid() );
return 1;
}
int func()
{
int pid = fork();
if (pid==0) {
foo("child");
int pid2 = fork();
if (pid2==0) {
foo("child");
exit(0);
}
else {
wait(NULL);
}
int pid3 = fork();
if (pid3==0) {
foo("child");
exit(0);
}
else {
wait(NULL);
}
exit(0);
}
else {
wait(NULL);
}
int pid1 = fork();
if (pid1==0) {
foo("child1");
int pid4 = fork();
if (pid4==0) {
foo("child");
exit(0);
}
else {
wait(NULL);
}
int pid5 = fork();
if (pid5==0) {
foo("child");
exit(0);
}
else {
wait(NULL);
}
exit(0);
}
else {
wait(NULL);
}
return 0;
}
int main()
{
foo("parent");
func();
return 0;
}
output :
I am a parent. My pid is:37 my ppid is 18
I am a child1. My pid is:38 my ppid is 37
I am a child2. My pid is:39 my ppid is 38
I am a child3. My pid is:40 my ppid is 38
I am a child4. My pid is:41 my ppid is 37
I am a child. My pid is:42 my ppid is 41
I am a child5. My pid is:43 my ppid is 41
As I assume that Raj understood fork() and wait() but did not yet get the concept of binary trees (and how to implement them using recursive functions) I made a small complete sample for this. It prevents the usage of fork() to make the binary tree/recursion concept more clear.
Putting it altogether:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
void foo()
{
printf("child process %d, (%d)->(%d)\n",
getpid(), getppid(), getpid());
}
/* creates child processes in binary tree manner.
*
* n ... number of tree nodes (child processes) to create
*/
void do_fork(int n)
{
if (n <= 0) return;
int n1 = n / 2;
int n2 = n - n1;
int pid1 = 0, pid2 = 0;
if (n1 >= 0) {
--n1;
pid1 = fork();
if (pid1 < 0) {
fprintf(stderr, "ERROR: fork failed in process %d!\n", getpid());
return;
}
if (pid1 == 0) {
foo();
do_fork(n1);
exit(0);
}
}
if (n2 >= 0) {
--n2;
pid2 = fork();
if (pid2 < 0) {
fprintf(stderr, "ERROR: fork failed in process %d!\n", getpid());
return;
}
if (pid2 == 0) {
foo();
do_fork(n2);
exit(0);
}
}
wait(NULL);
}
int main(int argc, char **argv)
{
int n = 3; /* number of binary tree nodes, might become input */
printf("parent process %d, children to create: %d\n", getpid(), n);
if (n) do_fork(n);
return 0;
}
I compiled and tested this with gcc on cygwin:
$ gcc -o test-bin-tree-fork test-bin-tree-fork.c
$ ./test-bin-tree-fork.exe
parent process 8628, children to create: 3
child process 13608, (8628)->(13608)
child process 7292, (8628)->(7292)
child process 8920, (7292)->(8920)
child process 14104, (7292)->(14104)
I'm having problems, I need to make a program that make 9 child processes, after that I have to put a countdown of 3 seconds and make these 9 processes to wait for a signal from the father, after they receive this signal, every children should say what children he is (if he is the children #1, #2, #3, etc..., in order in which they were made).
What I've done is here, everything is OK, I think, until the part where I have to say as a children, what is my number, I don't have a clue how to do it, because each children is a different process, they don't share memory and the signal can't use arguments for that, by now I'm printing the PID on the function called "handler", but how can I print my number, as a Children?.
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
void handler(int x);
int main() {
pid_t child[9];
pid_t child_pid;
for (int i = 0; i < 9; ++i) {
child_pid = fork();
child[i] = child_pid;
if (child_pid == 0)
break;
if (child_pid < 0) {
perror("fork()");
exit(EXIT_FAILURE);
}
}
if (child_pid == 0) {
signal(SIGUSR1, handler);
pause();
} else {
printf("Countdown:\n");
sleep(1);
printf("3\n");
sleep(1);
printf("2\n");
sleep(1);
printf("1\n");
sleep(1);
for (int i = 0; i < 9; i++)
kill(child[i], SIGUSR1);
waitpid(-1, NULL, 0);
}
return 0;
}
void handler(int sig) {
printf("This is Child #%d\n", getpid());
exit(0);
}
Create a global variable:
int my_number;
Then in your loop that creates the children, do:
if (child_pid == 0) {
my_number = i;
break;
}
Then you can use the variable in the handler:
void handler(int sig) {
printf("This is Child #%d\n", my_number);
exit(0);
}
I m trying to implement a program using pipes where parent process accepts a string and passes it to child process. Need to be done with only single pipe. How does the pipe read & write accepts string.
Here is my sample code! all!
#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
using namespace std;
int main()
{
int pid[2];
ssize_t fbytes;
pid_t childpid;
char str[20], rev[20];
char buf[20], red[20];
pipe(pid);
if ((childpid = fork()) == -1) {
perror("Fork");
return(1);
}
if (childpid == 0) {
// child process close the input side of the pipe
close(pid[0]);
int i = -1, j = 0;
while (str[++i] != '\0') {
while(i >= 0) {
rev[j++] = str[--i];
}
rev[j] = '\0';
}
// Send reversed string through the output side of pipe
write(pid[1], rev, sizeof(rev));
close(pid[0]);
return(0);
} else {
cout << "Enter a String: ";
cin.getline(str, 20);
// Parent process closing the output side of pipe.
close(pid[1]);
// reading the string from the pipe
fbytes = read(pid[0], buf, sizeof(buf));
cout << "Reversed string: " << buf;
close(pid[0]);
}
return 0;
}
You never pass the string to be reversed to the child, so it reverses some random garbage and sends it to the parent.
Minor issues:
write(pid[1], rev, sizeof(rev));
close(pid[0]); // Should be pid[1]
return(0); // Should be _exit(0)
The reason you don't want to return from main in the child is that you don't know what consequences that will have. You may call exit handlers that manipulate real world objects that the parent expects to remain intact.