Does fork() duplicate only the calling thread or all threads? - process

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int i = 0;
fork();
for(;i<3; ++i)
printf("%d", i);
fork();
return 0;
}
Here is my code. I want to know how many processes do I have after executing the last fork()

Fork splits the current process into 2 processes, so you have 2 after the first fork and 4 after the second.
Edit: After the first fork() there will be two processes, both executing the following statements. The initial process and the forked process will both call fork() the second time, resulting in 4 total processes after that call. For more info check out this link: http://www.csl.mtu.edu/cs4411.ck/www/NOTES/process/fork/create.html

Related

Shared mutex between process

I am learning mutex usage between process. I have a question w.r.t this.
Since each process has its own address space, the mutex defined by one process cannot be seen by another. On googling, I came across usage of pthread_mutex_setpshared() to get this done. I am attaching my code below. But looks like even now, the mutex is not shared between processes. How is this to be modified.
I know this can be achieved using named semaphore. But want to know the usage using mutex.
#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <semaphore.h>
#include <fcntl.h>
int main()
{
pid_t pid;
int ch = 0;
//sem_t *s1;
//s1 = sem_open("/sem", O_CREAT, 0666, 0);
pthread_mutex_t m1;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&m1, &attr);
pid = fork();
if(pid == 0)
{
pthread_mutex_lock(&m1);
printf("\nChild process");
printf("\nPress 1 to unlock from child:");
scanf("%d", &ch);
if(ch == 1)
{
pthread_mutex_unlock(&m1);
}
//sem_post(s1);
}
else if (pid > 0)
{
pthread_mutex_lock(&m1);
//sem_wait(s1);
printf("\nParent process");
printf("\nPress 2 to unlock from parent:");
scanf("%d", &ch);
if(ch == 2)
{
pthread_mutex_unlock(&m1);
}
}
else
{
printf("\nError");
}
}
As well as setting the PTHREAD_PROCESS_SHARED attribute, you need to arrange to have the mutex itself (your m1 variable) stored in shared memory, accessible by both processes. A duplicate, as created by your fork(), does not work.
If you use mmap() to create an anonymous mapping with the MAP_SHARED flag, and allocate the mutex within that, then it will be shared between the processes after the fork() and will work.

system() call always fail with -1

I have a process which returns always -1 on system() call, but other processes on the same system do not have this error. I'm clueless to why this process is always returning -1 on the system() call. The command with which the system() is invoked is also successful. It just that it always returns -1.
The issue is due to signal(SIGCHLD, SIG_IGN) for that process.
When SIGCHLD is ignored, then waipid should not be called after a fork.
But it looks like system call always call waitpid and this will cause the system to return -1.
#include <signal.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
int ret = 0;
signal(SIGCHLD, SIG_IGN);
ret = system("echo hello!!");
printf("ret=%d errno=%d error=%s\n",ret,errno,strerror(errno));
}
bash-3.2$ ./a.out
hello!!
ret=-1 errno=10 error=No child processes
bash-3.2$

SC_THREAD does not get triggered by its sensitivity list

I am developing a simple NAND module in SystemC. By specification, it should have a 4 ns delay so I tried to describe it with a process with a "wait" statement and SC_THREAD, as follows:
//file: nand.h
#include "systemc.h"
SC_MODULE(nand2){
sc_in<bool> A, B;
sc_out<bool> F;
void do_nand2(){
bool a, b, f;
a = A.read();
b = B.read();
f = !(a && b);
wait(4, SC_NS);
F.write(f);
}
SC_CTOR(nand2){
SC_THREAD(do_nand2);
sensitive << A << B;
}
};
To simulate I've created another module the outputs the stimulus for the NAND, as follows:
//file: stim.h
#include "systemc.h"
SC_MODULE(stim){
sc_out<bool> A, B;
sc_in<bool> Clk;
void stimGen(){
wait();
A.write(false);
B.write(false);
wait();
A.write(false);
B.write(true);
wait();
A.write(true);
B.write(true);
wait();
A.write(true);
B.write(false);
}
SC_CTOR(stim){
SC_THREAD(stimGen);
sensitive << Clk.pos();
}
};
Having these two modules described, the top module (where sc_main is) looks like this:
//file: top.cpp
#include "systemc.h"
#include "nand.h"
#include "stim.h"
int sc_main(int argc, char* argv[]){
sc_signal<bool> ASig, BSig, FSig;
sc_clock Clk("Clock", 100, SC_NS, 0.5);
stim Stim("Stimulus");
Stim.A(ASig); Stim.B(BSig); Stim.Clk(Clk);
nand2 nand2("nand2");
nand2.A(ASig); nand2.B(BSig); nand2.F(FSig);
sc_trace_file *wf = sc_create_vcd_trace_file("sim");
sc_trace(wf, Stim.Clk, "Clock");
sc_trace(wf, nand2.A, "A");
sc_trace(wf, nand2.B, "B");
sc_trace(wf, nand2.F, "F");
sc_start(400, SC_NS);
sc_close_vcd_trace_file(wf);
return 0;
}
The code was compiled and simulated with no errors, however when visualizing the .vcd file in gtkwave the output (F) gets stuck in 1, only showing the delay in the beginning of the simulation.
To test if there were any errors in the code I removed the "wait" statements and changed SC_THREAD to SC_METHOD in the nand.h file and simulated again, now getting the correct results, but without the delays of course.
What am I doing wrong?
It's best if you use an SC_METHOD for process do_nand2, which is sensitive to the inputs. A thread usually has an infinite loop inside of it and it runs for the entire length of the simulation. A method runs only once from beginning to end when triggered. You use threads mostly for stimulus or concurrent processes and threads may, or may not be sensitive to any events.
Just solved the problem:
instead of using
wait(4, SC_NS);
with SC_THREAD I used
next_trigger(4, SC_NS);
with SC_METHOD and it worked just fine.

API for handling wait queues are not working

I have to make tasks as processes in Linux but I don't want the process to execute until all the processes are created. So I thought of moving the processes to wait queue soon after creation and wait until all processes are created.
#include <unistd.h> /* Symbolic Constants */
#include <sys/types.h> /* Primitive System Data Types */
#include <errno.h> /* Errors */
#include <stdio.h> /* Input/Output */
#include <stdlib.h> /* General Utilities */
#include <pthread.h> /* POSIX Threads */
#include <string.h> /* String handling */
#include <sched.h>
#include <linux/kernel.h>
#include <time.h>
#include <sys/resource.h>
#include <stddef.h>
#include <linux/sched.h>
#include <linux/wait.h> /* for wait_event_interruptible() & wake_up_interruptible() */
int done = 0;
static DECLARE_WAIT_QUEUE_HEAD(queue);
int main()
{
int pid1, pid2;
if ((pid1 = fork()) < 0) //create a child process
exit(1);
if ((pid2 = fork()) < 0) //create a child process
exit(1);
if (pid1 == 0) //child process
{
wait_event_interruptible(queue, done == 2);
printf("child 1\n");
}
else //parent process
{
done = done+1;
wake_up_interruptible(&queue);
}
if (pid2 == 0) //child process
{
wait_event_interruptible(queue, done == 2);
printf("child 2\n");
}
else //parent process
{
done = done+1;
wake_up_interruptible(&queue);
}
return 0;
}
But when I tried this sample code it shows these errors.
$ gcc -Wall try.c
try.c:18:8: warning: type defaults to ‘int’ in declaration of ‘DECLARE_WAIT_QUEUE_HEAD’ [-Wimplicit-int]
try.c:18:1: warning: parameter names (without types) in function declaration [enabled by default]
try.c: In function ‘main’:
try.c:33:6: warning: implicit declaration of function ‘wait_event_interruptible’ [-Wimplicit-function-declaration]
try.c:33:31: error: ‘queue’ undeclared (first use in this function)
try.c:33:31: note: each undeclared identifier is reported only once for each function it appears in
try.c:39:2: warning: implicit declaration of function ‘wake_up_interruptible’ [-Wimplicit-function-declaration]
try.c: At top level:
try.c:18:8: warning: ‘DECLARE_WAIT_QUEUE_HEAD’ declared ‘static’ but never defined [-Wunused-function]
When I checked $ man wait_event_interruptible, it says "No manual entry for wait_event_interruptible". So the API is missing in the library. How can I add it to the library? Thanks in advance.
wait_event_interruptible(), wake_up_interruptible() are some of the Kernel's API to create and use wait queues. You cannot use those from the user-land!
If I understand your purpose correctly, what you need to do is to create N processes barrier. If you know the number of the processes (N), you can easily use semaphores: initialize the semaphore with zero, all processes call down() and the last process calls up() N times. You can also use message queues.
You can also use the Linux API for barriers: pthread_barrier_wait and pthread_barrier_init, but I have not used this before.

Why doesn't fork() create multiple processes, or does it?

We had a school exercise today to create multiple processes. Our problem was not the code itself neither the understanding of fork().
The problem me and my mate had were why it didn't create 4 processes of our code as shown below:
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
//kod
int child1();
int child2();
int main() {
pid_t pid1, pid2;
int i;
pid1 = fork();
pid2 = fork();
if(!pid1)
child1();
else if(!pid2)
child2();
else {
printf("parentlolololololol");
}
for(;;)
return 0;
}
int child1(){
for(;;) {
printf("A");
fflush(stdout);
sleep(1);
}
return 0;
}
int child2(){
for(;;){
printf("B");
fflush(stdout);
sleep(1);
}
return 0;
}
We have a sliced discussion whether the program creates 4 processes or not. Do the second fork()-call create a new process of the child and why isn't it being held up by any loop if that case? Or doesn't the second fork()-call create a new process of the child at all?
This is not relevant to our exercise in any way, but we're very curious, as you have to be as a programmer ;)
The issue is the missing semicolon on this line:
for(;;)
return 0;
This means that the main program will return 0 forever - actually only effective the first time.
After the first fork there are two processes, one where pid1 is 0 and one where it is not.
Each of these two processes then calls the second fork statement - two of them will have pid2 == 0 and two not.
main ---> fork --> pid1 == 0 --> fork --> pid2 == 0
--> pid2 != 0
--> pid1 != 0 --> fork --> pid2 == 0
--> pid2 != 0
So there are 4 processes. Entering the conditionals, two are caught by 'child1' and one is caught by 'child2'. The main process exits. That leaves 3 processes running, two printing 'A' and one printing 'B'.
It does - it forks twice unconditionally, creating 4 processes (well, 3 new ones anyway). Two of them should run child1(), one child2() and one the parent code. This is because you have 4 different values for the pid1/pid2 pair, and the first if covers two of them.