How to use fork to create a new process which will print its copy of arg? - argv

I have to Test argv by modifying this code and I have no idea what the question is asking me... I am just learning and very new to this whole thing.
use fork to create a new process which will print its copy of argv. The
parent process should also print its own copy of argv. Run the program and direct the
output to a temp file. Open the temp file and check if both child and parent processes
print the same set of arguments. Make sure the parent waits for its child before it
terminates.
int printList(char **someList)
{
int index=0;
while(someList[index]!=NULL)
{
printf("%s\n "someList[index]);
index++;
}
return index;
}
int main (int argc, char **argv, char **envp)
>{...
}```

In Linux, forking a process spawns a new "child process" which is an exact copy of the memory and state of execution of the parent (except the return value of the fork() call itself will be different). So your question is asking you to do something like
int main (int argc, char **argv, char **envp)
{
int pid = fork();
int output_fd = file.open("temp.txt")
if(pid == 0) {//This is the child process
fprintf(output_fd, "I am the child, my args are %s", argv);
exit(0);
}
//This is the parent process, wait for child to terminate then print argv
wait(pid);
fprintf(output_fd, "I am the parent, my args are %s", argv);
}
In the output file, you should see the both the parent and child process printed their args and that they have the same argv, because memory is copied from parent to child process when you make a fork() call.

Related

How to invoke an executable in the path /usr/bin using a C++ program?

I have an GUI based executable in the path /usr/bin in the linux machine
This executable takes three arguments - two integer values and one char
Can you let me know how to invoke and run this executable from a user space C++ program
Not leaving this unanswered for no reason
pid_t runprocess(int arg1, int arg2, char arg3)
{
static const char program[] = "/usr/bin/...";
char arg1c[12];
char arg2c[12];
char arg3c[2];
sprintf(arg1c, "%d", arg1);
sprintf(arg2c, "%d", arg2);
arg3c[0] = arg3;
arg3c[1] = 0;
pid_t pid = vfork();
if (pid == 0) {
signal(SIGHUP, SIG_IGN); /* since it's a GUI program, detach from console HUP */
close(0); /* and detach from stdin */
if (open("/dev/null", O_RDWR)) _exit(137); /* assertion failure */
execl(program, program, arg1c, arg2c, arg3c, NULL);
_exit(errno);
}
return pid;
}
Build arguments as strings, fork and exec it. Trivial really. Don't forget to wait().
Since the child process is a GUI process, we detach HUP from the terminal we may or may not be running on and replace stdin with /dev/null.

How to make system() function unblocking?

I am calling an executable from another executable in android Linux. Following is the relevant code:
...
int status = system("/system/bin/executable");
...
My requirement is not to wait for the executable to complete its execution. Means I want to run executable independent of the executable that calls it.
I have searched over the internet and didn't find how to make this system call non-blocking. Please help me to resolve it.
The system() function, without error handling, looks like this:
int system(char const *cmdline)
{
pid_t pid = fork();
if(pid == 0)
{
char const *argv[] = { "sh", "-c", cmdline, NULL };
execve("/bin/sh", argv, NULL);
_exit(1);
}
else
{
int status;
waitpid(pid, &status, 0);
return status;
}
}
The command itself is parsed by the shell, so you can use the normal & suffix to send the command into the background. The shell then terminates immediately, the background program is reparented to PID 1 (so your program isn't responsible for collecting the zombie), and system() returns.
I am able to achieve non-blocking with following code:
if (fork() == 0)
{
char *args[] = {..., NULL};
char *env[] = {..., NULL};
if (execve("/system/bin/executable", args, env) == -1)
print("Error: [%d]", errno);
}
There are few importants thing here:
fork() will create a new process. So from line if(fork() == 0), there will be 2 process running in the same space of main program.
Both processes continue executing from the point where the fork( ) calls returns execution to the main program..
fork() == 0 will let only child process in the if condition.
execve(..) will replace child process program(which is its parent program from which it copied by fork command) with /system/bin/executable.
execve(..) will not return if it get success in runing the executable else return -1.
In case of execve(..) failure the errno will be filled with the actual error.
Please correct me if I am wrong. I hope it will help someone.

How to propagate signal in C from parent to child which are in own process group?

Suppose I have 10 child processes which are moved to their own process group by setpgid(0,0) just before the exec. (Each child also has children which are also in their own process group.)
My foreground process gets ctrl-c SIGINT signal and I want to propagate it to the all child processes (all children are in different group). How to do that?
hope that quick draft better explain my problem.
void handler(int signal) {
// resend SIGINT to all childs but childs are in different pgid
}
int main(int argc, char* argv[]){
struct sigaction sa;
sa.sa_handler = &handler;
sigaction(SIGINT, &sa, NULL);
pid_t pid[SIZE];
int i = 0;
// if argv is ge 2;
for (;i < SIZE; i++) // SIZE is number of the elements in argv
{
pid[i] = fork();
if(pid[i] == 0)
{
setpgid(0,0);
// execv self here but with one less element in argv;
}
}
while(1){}; // infinity loop (waits for ctrl-c from foreground process)
// prints to the terminal pid and pgid
// waits here for all childs to finish and then close self
}
What about forwarding the signal in the signal handler of main process, manually. Maybe you can provide some code snippet to clarify the situation you're in.
void signalHandler(int signum)
{
kill(child_pid,signum);
//other stuff
}

About Inter-process communication in C, Using pipe()

I'm trying to write sort function.
This function may fork many children to help itself to sort the given input.
When my function has only one child it is easy to use pipe(). I just create
int fd[2];
then everything is fine but I don't know what to do when there are many children. Should I create fd[Children*2] pipes or fd[2] is enough?
And how can i use these pipes to communicate with the child that I want (since there are many children)?
My main process will fork children, this is just one part of the code, I'm forking children and getting their pids into pid array
pid_t main = getpid();
int N = 30;
pid_t* children = (pid_t*) malloc(sizeof(pid_t) * N);
for(i = 0; i < N; i++){
pid_t child = fork();
if ( child == 0){
pid_t me = getpid();
printf("I'm a child and my pid is: %d\n", me);
sleep(1);
// exit(4);
return me * 2;
} else if ( child < 0){
// printf("Could not create child\n");
} else {
children[i] = child;
// printf("I have created a child and its pid %d\n", child);
}
}
If only the main process needs to create and communicate with children, and the children don't need to communicate with each other, create a separate pipe for each child in the main process before forking the child. The call to pipe() could be placed in your loop, before calling fork(). You could use a 2-dimensional array like fd[NUM_CHILDREN][2] to keep track of the file descriptors. If the data will be arriving asynchronously, poll() or select() can be used to find out when something is available to be read.

Unexplainable behaviour with replecating manual piping using dup2

I have two sets of code both trying to execute something like ls|grep pip
One that works and one that does not.
The working code creates 2 child process and uses one child each to execlp the one command and the other simply tries to do this by creating one child. I.e executing ls in say the child and the grep in the parent. This does not seem to work. And I can't seem to get any error either.
Can someone tell me what the problem is? And why it exists?
Not Working:
void runpipe()
{
pid_t childpid;
int fd[2];
pipe(fd);
int saved_stdout;
int saved_stdin;
saved_stdout=dup(STDOUT_FILENO);
saved_stdin=dup(STDIN_FILENO);
if((childpid=fork())==0)
{
dup2(fd[WRITE_END],STDOUT_FILENO);
close(fd[WRITE_END]);
execlp("/bin/ls","ls command","-l",NULL);
dup2(STDOUT_FILENO,fd[1]);
_exit(0);
}
else if(childpid>0)
{
dup2(saved_stdout,STDOUT_FILENO);
dup2(fd[READ_END],STDIN_FILENO);
close(fd[READ_END]);
execlp("/bin/grep","grep","pip",NULL);
wait();
_exit(0);
}
else
{
printf("ERROR!\n");
}
}
Here are the codes:
Working:
int runpipe(){
pid_t pid;
int fd[2];
pipe(fd);
int i;
pid=fork();
if (pid==0) {
printf("i'm the child used for ls \n");
dup2(fd[WRITE_END], STDOUT_FILENO);
close(fd[READ_END]);
execlp("ls", "ls", "-al", NULL);
_exit(0);
} else {
pid=fork();
if (pid==0) {
printf("i'm in the second child, which will be used to grep\n");
dup2(fd[READ_END], STDIN_FILENO);
close(fd[WRITE_END]);
execlp("grep", "grep","pip",NULL);
}
else wait();
}
return 0;
}
The parent needs to close the write side of the pipe before exec'ing grep. For some reason, your code with the two children closes that file descriptor, but does not in the code with only one child. You are leaving several descriptors open, but the write side on the pipe is the important one. The reader (the exec'd grep) will not finish until all copies of the write side of the pipe are closed. By failing to close it, the grep is the one holding it open so grep will never terminate, but just wait for more data.

Resources