#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<string.h>
#include<sys/stat.h>
#define SIZE 100
void main()
{
int shmid,status;
pid_t pid;
int i;
char *a,*b,d[100];
shmid=shmget(IPC_PRIVATE,SIZE,S_IRUSR | S_IWUSR);
pid=fork();
if(pid==0)
{
b=(char *) shmat(shmid,NULL,0);
printf("enter");
printf("%c",*b);
shmdt(b);
}
else
{
a=(char *) shmat(shmid,NULL,0);
printf("enter a string");
scanf("%s",&d);
strcpy(a,d);
shmdt(a);
}
}
I was trying to pass a string from the parent process to the child process. But before scanning the value into "d" the program switches to the child process. How should I correct this logical error? And how should I pass this string "d" to the child process?
After call to fork was made you never know which process will execute first. You must simply assert your code handles properly interprocess communication, whatever happens now.
You can use pipe(2) or shared memory to pass data between different processes on same host.
#include <unistd.h>
int pipe(int pipefd[2]);
But you can also read data into global variable before call to fork. Fork will create a copy of global data in new process.
Shared memory using shmget example.
Fork is a system call and it creates two processes one is called the parent and the other is called the child!
To enable them to communicate you need to apply interprocess communication techniques
You could use
1.Pipes
2.FIFO-also known as Named pipes
3.Shared Memory
4.Message Queue
5.Semaphore
Everything you need to know to use them is mentioned here!The sample codes are written after the description
Related
Basically I know how to solve the program so that it does what it's suppose to do correctly(which is calculating the multiplication times 10 of a number entered by the user) by adding wait and kill, but I don't understand why it doesn't work as it is. I though the read were blocking but in this case, it seems the read don't block since they don't seem to wait for entries in the pipe. The read of the parents should block until there is a value inside.
Here is the program I'm talking about, why does the entry 1 returns 1 instead of 10? In what order are applied the system call in that case? Is this because the read of the parent reads pfd[1] while var is written in the pipe before the write of the child as the time to take place? I thought the read of the child would clean what is in the pipe before the read of the parent take place.
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
int multi(int var) {
int multi;
int pfd[2];
pipe(pfd);
int pid = fork();
if (pid>0) {
write(pfd[1], &var, sizeof(var));
read(pfd[0], &multi, sizeof(multi));
close(pfd[0]);
} else {
read(pfd[0], &var, sizeof(var));
multi = 10 * var;
write(pfd[1], &multi, sizeof(multi));
close(pfd[1]);
}
return multi;
}
int main(void) {
int x;
fscanf(stdin, "%d", &x);
printf("%d\n", multi(x));
}
The order of execution of the parent and child is unpredictable. If the parent executes its read(pfd[0]) before the child does, it will simply read what it just wrote. Adding a call to wait() ensures that the parent won't try to read from the pipe until after the child has read and written the reply.
Another solution is to use two pipes, one for parent->child communication, and another for child->parent.
Within the child process, is there any way that it determine whether it was launched as a fork with overlay memory, or a vfork with shared memory?
Basically, our logging engine needs to be much more careful (and not log some classes of activity) in vfork. In fork it needs to cooperate with the parent process in ways that it doesn't in vfork. We know how to do those two things, but not how to decide.
I know I could probably intercept the fork/vfork/clone calls, and store the fork/vfork/mapping status as a flag, but it would make life somewhat simpler if there was an API call the child could make to determine its own state.
Extra marks: Ideally I also need to pick up any places in libraries that have done a fork or vfork and then called back into our code. And how that can happen? At least one of the libraries we have offers a popen-like API where a client call-back is called from the fork child before the exec. Clearly the utility of that call-back is significantly restricted in vfork.
All code not specifically designed to work under vfork() doesn't work under vfork().
Technically, you can check if you're in a vfork() child by calling mmap() and checking if the memory mapping was inherited by the parent process under /proc. Do not write this code. It's a really bad idea and nobody should be using it. Really, the best way to tell if you're in a vfork() child or not is to be passed that information. But here comes the punchline. What are you going to do with it?
The things you can't do as a vfork() child include calling fprintf(), puts(), fopen(), or any other standard I/O function, nor malloc() for that matter. Unless the code is very carefully designed, you're best off not calling into your logging framework at all, and if it is carefully designed you don't need to know. A better design would most likely be log your intent before calling vfork() in the first place.
You ask in comments about a library calling fork() and then back into your code. That's already kind of bad. But no library should ever ever call vfork() and back into your code without being explicitly documented as doing so. vfork() is a constrained environment and calling things not expected to be in that environment really should not happen.
A simple solution could use pthread_atfork(). The callbacks registered with this service are triggered only upon fork(). So, the 3rd parameter of the function, which is called in the child process right after the fork, could update a global variable. The child can check the variable and if it is modified, then it has been forked:
/*
Simple program which demonstrates a solution to
make the child process know if it has been forked or vforked
*/
#include <pthread.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
pid_t forked;
void child_hdl(void)
{
forked = getpid();
}
int main(void)
{
pid_t pid;
pthread_atfork(0, 0, child_hdl);
pid = fork();
if (pid == 0) {
if (forked != 0) {
printf("1. It is a fork()\n");
}
exit(0);
}
// Father continues here
wait(NULL);
pid = vfork();
if (pid == 0) {
if (forked != 0) {
printf("2. It is a fork()\n");
}
_exit(0);
}
// Father continues here
wait(NULL);
return 0;
}
Build/execution:
$ gcc fork_or_vfork.c
$ ./a.out
1. It is a fork()
I came across kcmp today, which looks like it can answer the basic question - i.e. do two tids or pids share the same VM. If you know they represent forked parent/child pids, this can perhaps tell you if they are vfork()ed.
Of course if they are tids in the same process group then they will by definition share VM.
https://man7.org/linux/man-pages/man2/kcmp.2.html
int syscall(SYS_kcmp, pid_t pid1, pid_t pid2, int type,
unsigned long idx1, unsigned long idx2);
KCMP_VM
Check whether the processes share the same address space.
The arguments idx1 and idx2 are ignored. See the
discussion of the CLONE_VM flag in clone(2).
If you were created by vfork, your parent will be waiting for you to terminate. Otherwise, it's still running. Here's some very ugly code:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
void doCheck()
{
char buf[512];
sprintf(buf, "/proc/%d/wchan", (int) getppid());
int j = open(buf, O_RDONLY);
if (j < 0) printf("No open!\n");
int k = read(j, buf, 500);
if (k <= 0) printf("k=%d\n", k);
close(j);
buf[k] = 0;
char *ptr = strstr(buf, "vfork");
if (ptr != NULL)
printf("I am the vfork child!\n");
else
printf("I am the fork child!\n");
}
int main()
{
if (fork() == 0)
{
doCheck();
_exit(0);
}
sleep(1);
if (vfork() == 0)
{
doCheck();
_exit(0);
}
sleep(1);
}
This is not perfect, the parent might be waiting for a subsequent vfork call to complete.
This code below is supposed to execute external programs passed as arguments to the main
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
int main(int argc ,char* argv[])
{
int e =0;
int* f=&e;
printf("%p\n",f);
pid_t p ;
for(int i=1;i<argc;i++)
{
p=fork();
wait(NULL);
if(p==0)
{
printf("\n---------------------\n");
execvp(argv[i],&argv[i]);
printf("erreur \n");
(*f)=(*f)+1;
printf("%d\n",*f);
printf("%p\n",f);
exit();
}
}
if(p>0)
{
printf("erreurs: %d \n",*f );
}
return 0;
}
The program also aims to show how many errors occured. However, the variable e=0 remains 0 even if the pointer *f pointing to its address was incremented inside the child fork.
How do I fix this problem?
When you call fork the process is duplicated. The parent and the child each have their own private memory maps, their own set of all variables. It's not possible for one process to change the value of another process variables.
If you want to share data between two processes you should use other inter-process communication methods, like for example shared memory.
I have these silly doubts relating to fork() system call,
Shall be grateful if anyone please answer these questions.
Does fork() system call returns an integer? If yes,then why while
executing the fork() system call,we are taking its value in pid_t?
Can't we just write int x=fork();
For eg-
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
pid_t pid;
pid=fork();
if(pid==0)
{
printf("Child Process");
}
else if(pid>0)
{
printf("Parent Process");
}
else
{
printf("Unable to create");
}
}
Why we are executing pid=fork() instead of int x=fork()?
The above program gives an output- Parent ProcessChild Process Why it
is first executing the parent process and not the child?
I have tried this code-
#include<stdio.h>
int main()
{
int x;
x=fork();
if(x==0)
{
printf("Child Process");
}
else if(x>0)
{
printf("Parent Process");
}
else
{
printf("Unable to create");
}
}
I have tried to collect the value of fork() in an integer variable
in gcc compiler of ubuntu 15.04 and its working fine,not showing
any error and giving the same result as the above program will
give.
Is it the compiler problem or is this code fine?
Even I haven't given the header fies sys/types.h and unistd.h,still not
showing any errors.
Can someone
please give an answer to my queries?
Using pid_t means that the source code is portable to e.g. systems that use a 64-bit PID.
The processes execute in that order because that is how the scheduler has decided to execute them.
Here pid_t is the 64-bit unsigned int, You can find it out in header files. This basically used to make the program portable.
Why parent process first?
Ans:
1 . After forking a process child had to copy the memory layout of parent process ( copying the head, stack, initialized data, uninitialized data ), So that time parent has nothing to do, So in most of the cases, parent has to execute first.
But in a few cases when child executes first, only when parent scheduling time expires.
In UNIX system /proc/sys/kernel/sched_runs_first, make this value 1 to make sure that the child process runs first.
In Conclusion, this behavior is not defined and undetminstic, Better to use any syncing methods.
I have an assignment in which I need to declare a pipe in a header file. I really have no idea how to do this. It might be a really stupid question and I might be missing something obvious. If you could point me in the right direction I would greatly appreciate it.
Thanks for your time.
EDIT:
Sorry about the question being so vague. Maybe I need to reinforce my understanding of pipes.
I'm trying to create a pipe between two child processes. One child will write random characters into the pipe while the other child will read characters out of the pipe.
I guess I don't really understand what happens when I write something like:
int fd[2];
pipe = pipe(fd);
Am I right in saying that the writing and reading file descriptors for the pipe are put into fd[0] and fd[1] respectively? If in one of the child processes I close fd[1], that child could be thought of as my writer, correct?
EDIT 2:
Okay, it looks as if I pretty much have everything figured out and done, except I am getting an error pertaining to the file descriptors.
My code looks like this: (This is only the code relating to the pipe)
proj2.h
extern int fd[2];
proj2.c
int fd[2];
pipe(fd);
writer.c
close(fd[0]);
result = write(fd[1], &writeBuffer, sizeof(writeBuffer));
if(result < 0){
perror("Write");
}
reader.c
close(fd[1]);
result = read(fd[0], &readBuffer, sizeof(readBuffer))
if(result < 0){
perror("Read");
}
After executing the code, I get an error for every iteration of read() and write() with the error "Bad file descriptor". I've tried searching online to solve this myself, but I do not think I know enough about this material in order to do so. Any direction would be greatly appreciated once again. Everybody that has contributed has done a wonderful job so far, thank you very much. Also, if it looks like I'm just having you do my homework for me, I'm putting forth an honest effort and this isn't the entirety of the assignment.
EDIT 3:
Is the write() system call writing to standard output? What if I only want the contents to be printed after the reader reads them out of the pipe? How do I write them into the pipe without it writing them to standard output?
EDIT 4:
I've figured everything out now. Thanks for all of the help everybody. The only thing I'm still curious about is if I could somehow get the status of the parent process. I've collected the statuses from the child process using the wait() system call and was wondering how to retrieve the status of the parent process.
Here's an example of a program that creates a pipe and then forks the process and calls a sender function in the parent and a receiver in the child. The pipe creation and file descriptors are in one source code file with an associated header file, as are the sender and receiver. The main file requests the pipe be created then does the fork() and calls the sender and receiver functions.
pipe.h - this contains the extern declaration for the pipe file descriptors as well as the declaration of the function that creates the pipe:-
#ifndef PIPE_H
#define PIPE_H
extern int pipe_fd[2];
void create_pipe(void);
#endif
pipe.c - contains the actual definition of the pipe_fd array:-
#include "pipe.h"
#include <unistd.c>
int pipe_fd[2];
void create_pipe(void)
{
pipe(pipe_fd);
}
sender.h - declares the prototype for the sender() function
#ifndef SENDER_H
#define SENDER_H
void sender(void);
#endif
sender.c:-
#include "sender.h"
#include "pipe.h"
#include <unistd.h>
#include <stdio.h>
void sender(void)
{
char buf[]="Hello world";
printf("Sender: PID = %d\n", getpid());
close(pipe_fd[0]);
write(pipe_fd[1], buf, sizeof(buf));
}
receiver.h:-
#ifndef RECEIVER_H
#define RECEIVER_H
void receiver(void);
#endif
receiver.c - mirror image of sender
#include <stdio.h>
#include <unistd.h>
#include "receiver.h"
#include "pipe.h"
void receiver(void)
{
int bytes;
char buf[101];
printf("Receiver: PID = %d\n", getpid());
close(pipe_fd[1]);
bytes = read(pipe_fd[0], buf, 100);
buf[bytes]='\0';
printf("Receiver got: %s\n", buf);
}
main.c - ties it all together
#include "pipe.h"
#include "sender.h"
#include "receiver.h"
#include <sys/types.h>
#include <unistd.h>
void launch_sender_receiver(void)
{
pid_t forkpid;
forkpid = fork();
if (forkpid == 0)
receiver(); /* child */
else
sender();
}
int main(int argc, char* argv[])
{
create_pipe();
launch_sender_receiver();
return 0;
}
Hopefully you can follow all this from the code but if not here's a little extra explanation.
The create_pipe() function in pipe.c creates a pipe and puts the two file descriptors into file_fd. The pipe.h file provides an extern declaration for the file descriptors so that they can be accessed by the sender and receiver files (better programming practice would be to provide "getter" functions for these file descriptors in pipe.h so that sender() and receiver() are not accessing global variables).
Sender and Receiver use the pipe_fd array to either write or read from the pipe after they close the file descriptor that they don't need. The main() function ties it all together by calling the pipe creation function and then doing the fork and calling sender or receiver depending on whether it is the parent or child respectively.
Running this as a complete program should get you the following output (although of course the PIDs you get will be different):-
Receiver: PID = 3285
Sender: PID = 3284
Receiver got: Hello world
Does all that make sense?
Your question is almost impossibly vague, but I'm going to guess
extern int myPipe[2];
?
If you intend to fork() to create the two processes then your "int fd[2]; pipe(fd);" will work as you described.
i.e. use fd[0] in one process and fd[1] in the other.
However, if you're not going to fork then you're probably going to have to create a pipe in the filesystem and communicate through this.
Use mkfifo to create your pipe and then open it for reading in one process and open it for writing in the other.
Why do you need to do it in a header file?
You just call pipe() from your program.
Then call fork().
As a result you have two processes accessing the same pipe.