问题
Given this code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#define BUF_SIZE 256
int main()
{
int fd1[2];
int fd2[2];
ssize_t numRead = -1;
// remark : working under the assumption that the messages are of equal length
const char* messageOne = "Hello world , I'm child number 1\n";
const char* messageTwo = "Hello world , I'm child number 2\n";
const unsigned int commLen = strlen(messageOne) + 1;
char buf[BUF_SIZE];
if (pipe(fd1) == -1)
{
printf("Error opening pipe 1!\n");
exit(1);
}
if (pipe(fd2) == -1)
{
printf("Error opening pipe 2!\n");
exit(1);
}
printf("Piped opened with success. Forking ...\n");
// child 1
switch (fork())
{
case -1:
printf("Error forking child 1!\n");
exit(1);
case 0:
printf("\nChild 1 executing...\n");
/* close reading end of first pipe */
if (close(fd1[0]) == -1)
{
printf("Error closing reading end of pipe 1.\n");
_exit(1);
}
/* close writing end of second pipe */
if (close(fd2[1]) == -1)
{
printf("Error closing writing end of pipe 2.\n");
_exit(1);
}
/* write to pipe 1 */
if (write(fd1[1], messageOne, commLen) != commLen)
{
printf("Error writing to pipe 1.\n");
_exit(1);
}
if (close(fd1[1]) == -1)
{
printf("Error closing writing end of pipe 1.\n");
_exit(1);
}
/* reding from pipe 2 */
numRead = read(fd2[0], buf, commLen);
if (numRead == -1)
{
printf("Error reading from pipe 2.\n");
_exit(1);
}
if (close(fd2[0]) == -1)
{
printf("Error closing reding end of pipe 2.\n");
_exit(1);
}
printf("Message received child ONE: %s", buf);
printf("Exiting child 1...\n");
_exit(0);
break;
default:
break;
}
// child 2
switch (fork())
{
case -1:
printf("Error forking child 2!\n");
exit(1);
case 0:
printf("\nChild 2 executing...\n");
/* close reading end of second pipe */
if (close(fd2[0]) == -1)
{
printf("Error closing reading end of pipe 2.\n");
_exit(1);
}
/* close writing end of first pipe */
if (close(fd1[1]) == -1)
{
printf("Error closing writing end of pipe 1.\n");
_exit(1);
}
/* read from the first pipe */
if (read(fd1[0], buf, commLen) == -1)
{
printf("Error reading from pipe 1.\n");
_exit(EXIT_FAILURE);
}
if (close(fd1[0]) == -1)
{
printf("Error closing reading end of pipe 1.\n");
_exit(EXIT_FAILURE);
}
/* write to the second pipe */
if (write(fd2[1], messageTwo, commLen) != commLen)
{
printf("Error writing to the pipe.");
_exit(EXIT_FAILURE);
}
if (close(fd2[1]) == -1)
{
printf("Error closing writing end of pipe 2.");
_exit(EXIT_FAILURE);
}
printf("Message received child TWO: %s", buf);
printf("Exiting child 2...\n");
_exit(EXIT_SUCCESS);
break;
default:
break;
}
printf("Parent closing pipes.\n");
if (close(fd1[0]) == -1)
{
printf("Error closing reading end of the pipe.\n");
exit(EXIT_FAILURE);
}
if (close(fd2[1]) == -1)
{
printf("Error closing writing end of the pipe.\n");
exit(EXIT_FAILURE);
}
if (close(fd2[0]) == -1)
{
printf("Error closing reading end of the pipe.\n");
exit(EXIT_FAILURE);
}
if (close(fd1[1]) == -1)
{
printf("Error closing writing end of the pipe.\n");
exit(EXIT_FAILURE);
}
printf("Parent waiting for children completion...\n");
if (wait(NULL) == -1)
{
printf("Error waiting.\n");
exit(EXIT_FAILURE);
}
if (wait(NULL) == -1)
{
printf("Error waiting.\n");
exit(EXIT_FAILURE);
}
printf("Parent finishing.\n");
exit(EXIT_SUCCESS);
}
This is a simple talk between two processes using pipe()
.
The output is :
Piped opened with success. Forking ...
Parent closing pipes.
Parent waiting for children completion...
Child 2 executing...
Child 1 executing...
Message received child TWO: Hello world , I'm child number 1
Exiting child 2...
Message received child ONE: Hello world , I'm child number 2
Exiting child 1...
Parent finishing.
As you can see from the above , the two children are speaking one with the other using fork
and pipe
. But I want to do this without piping them , is it possible ? if so please explain how , I don't want to use the pipe()
, what I do want to simulate pipe()
.
Thanks
回答1:
I have modified your program, to show an example of System V shared memory . To avoid race conditions semaphore (POSIX named semaphore) is also used. I have written some comments too. Pl. see if this example helps. Manual page of the individual functions can be referred to learn more about the functions. Compilation flag should be -lpthread. To generate the key (to refer an unique shared memory segment)an existing file (I have named it "anyfile") should be available in the current directory, since I have used ftok function. Pl. add proper error handlings too, by checking the return value of the functions.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <semaphore.h>
#define BUF_SIZE 256
int main()
{
key_t key;
char *virtualaddr;
sem_t *get, *put;
ssize_t numRead = -1;
int shmid;
const char* messageOne = "Hello world , I'm child number 1\n";
const char* messageTwo = "Hello world , I'm child number 2\n";
const unsigned int commLen = strlen(messageOne) + 1;
char buf[BUF_SIZE];
key = ftok("anyfile",'R');
shmid = shmget(key,1024,0644|IPC_CREAT);
if (0 > shmid)
{
perror("Shared Mem creation error\n");
exit(1);
}
//Attaching the shared mem to my address space(available across fork)
virtualaddr = shmat(shmid, (void*)0, 0);
/*Create two POSIX Named Semaphores, get and put and initialising with 0*/
get = sem_open("/get", O_CREAT|O_RDWR, 0644, 0);
put = sem_open("/put", O_CREAT|O_RDWR, 0644, 0);
// child 1
switch (fork())
{
case -1:
printf("Error forking child 1!\n");
exit(1);
case 0:
printf("\nChild 1 executing...\n");
//Referring the semaphores..
get = sem_open ("/get", O_RDWR);
put = sem_open ("/put", O_RDWR);
//Child 1 writing in shared mem
strcpy (virtualaddr, messageOne);
//Child 1 signalling that now child 2 can write
sem_post (get);
//Child1 waiting for Child2 to write..
sem_wait (put);
//Child 1 reading from shared mem
strcpy (buf, virtualaddr);
printf("Message received child ONE: %s", buf);
printf("Exiting child 1...\n");
_exit(0);
break;
default:
break;
}
// child 2
switch (fork())
{
case -1:
printf("Error forking child 2!\n");
exit(1);
case 0:
printf("\nChild 2 executing...\n");
//Referring the semaphores..
get = sem_open ("/get", O_RDWR);
put = sem_open ("/put", O_RDWR);
//Waiting Till Child 1 has written.
sem_wait (get);
//Now child 2 can read from shared memory
strcpy (buf, virtualaddr);
//Child 2 writing in shared mem
strcpy (virtualaddr,messageTwo );
//Signalling that now Child 1 can read.
sem_post (put);
printf("Exiting child 2...\n");
printf("Message received child TWO: %s", buf);
_exit(EXIT_SUCCESS);
break;
default:
break;
}
printf("Parent waiting for children completion...\n");
if (wait(NULL) == -1)
{
printf("Error waiting.\n");
exit(EXIT_FAILURE);
}
if (wait(NULL) == -1)
{
printf("Error waiting.\n");
exit(EXIT_FAILURE);
}
printf("Parent finishing.\n");
//Deleting semaphores..
sem_unlink ("/get");
sem_unlink ("/put");
//Deleting Shared Memory.
shmctl (shmid, IPC_RMID, NULL);
exit(EXIT_SUCCESS);
}
回答2:
Although why you would want to do this is beyond me, there are a couple of other IPC mechanism (all more complicated, and more error prone):
- Named Pipes (FIFOs)
- Shared Memory
- Mapped, Shared Memory
- UNIX-domain Sockets
- Internet-domain Sockets
For good tutorials of these, look at this e-book in the chapter "Interprocess Communication": Advanced Linux Programming
回答3:
You can use shared memory, or a Unix socket. Not sure why you'd ever want to though, if pipes are enough. Both shmem and sockets are more low-level.
回答4:
- Unix sockets
- Shared memory
- CORBA
- IPC message passing (see http://www.cs.cf.ac.uk/Dave/C/node25.html)
- TCP/IP or even UDP
- Could even write to a file and flag it using a semaphore for the other process to read.
Just off the top of my head
来源:https://stackoverflow.com/questions/11363731/how-can-2-processes-talk-to-each-other-without-pipe