is child process can run different program after fork() call? - process

A parent process creates a child process by calling the fork() system call. Both the parent and
child processes run the same program as fork creates an exact copy of the parent process. Is it
possible for the child process to run some other program? If yes then how, if no then why?

You can have different implementations in child and parent as fork() retuns 0 to child component and process id of child to parent.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void forkexample()
{
// child process because return value zero
if (fork() == 0)
printf("Hello from Child!\n");
// parent process because return value non-zero.
else
printf("Hello from Parent!\n");
}
int main()
{
forkexample();
return 0;
}

Related

Understanding how waitpid works with signals

Consider the following Pseudo-C code:
static int G = 0;
void alrm_handler(int signo) {
G = 1;
}
void son() {
struct sched_param param;
param.sched_priority = 50;
sched_setscheduler(getpid(),SCHED_FIFO, &param);
kill(getppid(), SIG_ALRM);
sched_yield();
printf("A\n");
while(1);
exit(0);
}
int main() {
signal(SIG_ALRM, alrm_handler);
int son_pid = fork();
if(son_pid==0)
son();
waitpid(son_pid);
printf("B\n");
return 0;
}
It's from an exam in OS. The question is as follows:
In multi cores CPU what would be printed?
The answers is that we can't know because it could be A and then B or B and then A. I don't understand why. If parent is waiting for the son with waitpid and the son sends signal SIG_ALRM which invokes the alrm_handler function for the parent, the parent will finish executing the function and then return to waiting the son until he will finish running, no? So it should be A and then B.
According to POSIX it is undefined whether system calls are restarted after a signal handler set by signal is called.
System V and the Linux signal system call do not restart system calls.
BSD and by default GLibc, do restart system calls.
If System V signal is used waitpid can return as soon the signal has been sent, allowing the letters to be printed in any order. If standard output is a pipe or regular file only B will be output as the child is in a infinite loop
With BSD signal only A will be printed as waitpid does not return due to the infinite loop in the child. If standard output is a pipe or regular file only nothing will be output.

Unable to set scheduling policy using sched_setscheduler() function?

I am new to OS programming. So, I wrote this code to change the scheduling policy of a background process, whose process ID I supply through a command line argument, but the sched_setscheduler() function fails, giving an error, "Function not implemented"
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]){
struct sched_param param;
param.sched_priority = 80;
int pid = atoi(argv[1]);
int policy = sched_getscheduler(pid);
printf("Current policy: %d\n", policy);
if(sched_setscheduler(pid, SCHED_FIFO, &param) == -1){
perror("Scheduler policy cannot be set");
}
int new_policy = sched_getscheduler(pid);
printf("New policy: %d\n", new_policy);
}
Can someone please tell me why this happening? Thanks.
So, I wrote this code to change the scheduling policy of a background process, whose process ID I supply through a command line argument
Here is the problem. sched_setscheduler(2) gets a thread id not a process id. For single thread processes PID and TID coincide, but in multi-threaded processes every thread has its own TID.
The fact that the argument is named pid and is of type pid_t might be misleading and even some old man-pages of sched_setscheduler(2) wrongly talk about processes, but this function is actually about threads.

Fork(), one process doesn't terminate?

I have never get this before; i'm doing a simple program: a father process which creates child processes, and after it terminates; this is the code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int child(pid_t pid)
{
printf("process %d is terminating\n",pid);
exit(EXIT_SUCCESS);
}
int main()
{
int i;
for(i = 0; i < 2; i++){
if(fork() == 0)
child(getpid());
}
printf("father, pid=%d terminated\n",getpid());
/*if(wait(NULL) == -1)
perror("wait");*/
exit(EXIT_SUCCESS);
}
when i run, all processes printed, but one process, i think father but i'm not sure, doesn't terminate because terminal is active(doesn't appear $);
insted, if i insert commented line with wait, program runs correctly; why this?
terminal output
If you look at the last run in the screen capture, you'll see "process 8429 is terminating" after the terminal prompt has been printed to the screen.
What appears to be happening is your "father" process happens to exit first, and your shell then outputs the prompt. Then, in the last case, the child process (PID 8429) printed its output and then exited.
So it is terminating, but sometimes the child process doesn't terminate until after the parent process exited and your shell process has already printed the prompt.
Just hit "enter" again when it does that, and you should see a proper shell prompt. Or even enter a command, and it should run normally.

How to avoid zombie processes? and what exactly init process does in this situation?

How to avoid zombie processes? and what exactly init process does in this situation?
I've seen this program,but not able to get it:
How does this program creates a zombie process:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void)
{
pid_t p = fork();
if (p != 0)
{
waitpid(p, NULL, 0); /* See if the child already had ended. */
sleep(1); /* Wait 1 seconds for the child to end. And eat away the SIGCHLD in case if arrived. */
pause(); /* Suspend main task. */
}
else
{
sleep(3); /* Just let the child live for some tme before becoming a zombie. */
}
return 0;
}
A child process turns into a zombie process when it did exit but the parent process did not yet run waitpid, wait or waitid on it. In a normal situation a parent would want to know the exit status on the child process it spawned and therefore woud run waitpid on the pid it got from fork.
What happens in your code above:
the child is spawned and exits (leaves the else clause and returns 0)
the parent runs into the endless pause loop until you press ctrl-c (the sleep and waitpid are superflous)
If you start the program and leave it running (./a.out &) and then run ps -fx then you see something like this:
6940 pts/1 SN 0:00 ./a.out
6943 pts/1 ZN 0:00 \_ [a.out] <defunct>
Now, if you kill the parent process (kill 6940) then the child becomes an orphan and the init process automatically becomes the new parent. Since the init process runs waitpid (aka "reaps" the child) on all processes it inherits the zombie process finally is deleted from the process table and does not show up any more via ps -f

how to iterate over PCB's to show information in a Linux Kernel Module?

I want to write a little Linux Kernel Module that can show me the PID of all running processes.
I have the following code:
/*
* procInfo.c My Kernel Module for process info
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
/*
* The init function, called when the module is loaded.
* Returns zero if successfully loaded, nonzero otherwise.
*/
static int mod_init(void)
{
printk(KERN_ALERT "ProcInfo sucessfully loaded.\n");
return 0;
}
/*
* The exit function, called when the module is removed.
*/
static void mod_exit(void)
{
printk(KERN_ALERT "ProcInfo sucessfully unloaded.\n");
}
void getProcInfo()
{
printk(KERN_INFO "The process is \"%s\" (pid %i)\n",
current->comm, current->pid);
}
module_init(mod_init);
module_exit(mod_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Rodrigo");
As you can see, i know i have to use the *struct task_struct* structure to get the PID and the Process name, but i am using current, and i know the existance of some double linked circular list that contains all PCB's, so the main question is:
what do i need to add to iterate over this linked lisk with p-next_task and p-prev_task so getProcInfo works?
Thanks!
The following macros from include/linux/sched.h may be useful:
#define next_task(p) \
list_entry_rcu((p)->tasks.next, struct task_struct, tasks)
#define for_each_process(p) \
for (p = &init_task ; (p = next_task(p)) != &init_task ; )
You probably need to hold the tasklist_lock before calling these macros; several examples of how to lock, iterate, and unlock, are in mm/oom_kill.c.
Actually, for newer kernels (2.6.18 and newer) the proper way to list tasks is by holding an rcu lock, because task list is now an RCU list. Also tasklist_lock is no more exported symbol - it means that when you are compiling a loadable kernel module, this symbol will not be visible for you.
example code to use
struct task_struct *task;
rcu_read_lock();
for_each_process(task) {
task_lock(task);
/* do something with your task :) */
task_unlock(task);
}
rcu_read_unlock();
Also documentation about RCU in linux kernel source directory can be helpful and you will find it in Documentation/RCU