I have a loop. Inside this loop I am trying to detect if a read or write is triggered on a named pipe (FIFO) file by using select().
If a read is triggered I call read() on the FIFO file descriptor.
If a write is triggered I call write() on the FIFO file descriptor.
The issue is that if a write occurs and I write to the FIFO, it will trigger a read. And then when I read from the FIFO it will trigger a write. Causing an infinite loop.
This loop occurs immediately if I use the same file descriptor in mode O_RDWR. This loop occurs after the first write if I create a separate file descriptor for both reading and writing.
#include <errno.h>
#include <sys/select.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
int main() {
// Open export fifo
int fd = open("./foo-fifo", O_RDWR | O_CREAT);
if (fd < 0) { // Failed to open
perror("error opening fifo");
}
// Read or write fifo until "quit" is in buffer
while (true) {
fd_set read_fds;
fd_set write_fds;
FD_ZERO(&read_fds);
FD_SET(fd, &read_fds);
FD_ZERO(&write_fds);
FD_SET(fd, &write_fds);
int num_fds = select(fd+1, &read_fds, &write_fds, NULL, NULL);
if (num_fds < 0) { // Failed to select
perror("failed to select fifo fd");
} else if (num_fds == 0) { // Timeout
continue;
}
// If read
if (FD_ISSET(fd, &read_fds)) {
char buf[1000] = "";
if (read(fd, buf, sizeof(buf)) < 0) {
perror("error reading fifo");
}
printf("read: \"%s\"\n", buf);
if (strcmp(buf, "quit\n") == 0) {
break;
}
}
// If write
if (FD_ISSET(fd, &write_fds)) {
char *buf = "foo";
if (write(fd, buf, sizeof(buf)) < 0) {
perror("error writing fifo");
}
printf("write: \"%s\"\n", buf);
}
}
// Close fifo
if (close(fd) < 0) { // Failed to close
perror("failed to close export fifo");
}
return 0;
}
Run the example by downloading the code from here (GitHub Gist). Then run:
gcc -o fifo fifo.c
./fifo
The output will show a loop between reading and writing:
write: "foo"
read: ""
write: "foo"
read: ""
write: "foo"
...
Note: This is prefaced by my top comments.
We need two processes (e.g. a server and a client).
fifos are single direction (a writer and a reader), not like a socket.
So, to do this with fifos, you'll need two of them. (e.g.) Given processes A and B, we need two pipes/fifos: pipeAB and pipeBA.
Process A writes to pipeAB and B reads from pipeAB.
Process B writes to pipeBA and A reads from pipeBA
If you want to use a socket, you could do a PF_UNIX (aka AF_UNIX) socket. See man 7 unix and man 2 socketpair.
Or, you could do a full blown AF_INET socket with the host set to localhost with some fixed port number.
As an exercise [for you], consider doing it in several ways. That is, an argv option like -Tp for dual pipes, -Tu for AF_UNIX, and -Ts for AF_INET, etc. Only the initialization would be different. The protocol would be nearly identical otherwise.
For AF_UNIX sockets, if the client and server are different programs, it may be easier to create a file of type socket in the file system. This can be done by filling in a struct sockaddr_un with the "filename" and then using bind after the socket call. See: https://www.ibm.com/support/knowledgecenter/en/SSB23S_1.1.0.13/gtpc1/unixsock.html for an example
Related
I write a test for FIFO. Server writes string "hello" to the client through FIFO. But it seems that the two processes are blocked.I think the FIFO are opened for writing and reading by server and client. But the two processes output nothing.
/* FIFO test */
#include <stdio.h>
#include <sys/types.h>
#include <sys.stat.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define FIFOPATH "/home/hel/fifo" // define file path
int client(void);
int server(void);
int main(void)
{
pid_t pid;
/* create FIFO */
if (mkfifo(FIFOPATH, S_IRUSR | S_IWUSR) < 0) {
if (errno == EEXIST) { // already exists, ok
}
/* error */
else {
exit(-1);
}
}
/* create process */
pid = fork();
if (pid < 0) { // error, process exits.
exit(-1);
} else if (pid == 0) { // child, server
server();
return 0; // exit
}
/* parent, client */
client();
return 0;
}
/* server */
int server(void)
{
int ret;
int fd;
/* open fifo for writing */
if ((fd = open(FIFOPATH, 0200)) < 0) {
printf("%s\n", strerror(errno));
return -1; // error
}
ret = write(fd, "hello", 5);
close(fd);
return 0;
}
/* client */
int client(void)
{
char recvBuf[100];
int fd;
int ret;
/* open fifo for reading */
if ((fd = open(FIFOPATH, 0400)) < 0) {
printf("%s\n", strerror(errno));
return -1; // error
}
ret = read(fd, recvBuf, 5);
printf("ret: %d %d\n", ret, fd);
printf("client receive %s\n", recvBuf);
close(fd);
return 0;
}
Your code has two problems. The first one is the main problem.
The flags parameters passed to open are incorrect. They are not supposed to be unix file permission flags as it appears you have provided. The server should use O_WRONLY and the client should use O_RDONLY.
write(fd, "hello", 5); and read(fd, recvBuf, 5); are not writing and reading the terminating NUL character of the string. But then it is printed as a string: printf("client receive %s\n", recvBuf);. This invokes Undefined Behaviour (even though there is a good chance the program may appear to "work"). Change 5 to 6.
open() uses following flags:-
O_RDONLY open for reading only
O_WRONLY open for writing only
O_RDWR open for reading and writing
O_NONBLOCK do not block on open or for data to become available
O_APPEND append on each write
O_CREAT create file if it does not exist
O_TRUNC truncate size to 0
O_EXCL error if O_CREAT and the file exists
O_SHLOCK atomically obtain a shared lock
O_EXLOCK atomically obtain an exclusive lock
O_NOFOLLOW do not follow symlinks
O_SYMLINK allow open of symlinks
O_EVTONLY descriptor requested for event notifications only
O_CLOEXEC mark as close-on-exec
for FIFO you must use O_RDONLY in client and O_WRONLY in server in your program.
0200 and 0400 permissions are not working for open(). you can check the the flag value in as
#define O_RDONLY 0x0000 / open for reading only */
#define O_WRONLY 0x0001 / open for writing only */
thats why open blocks in your case as it doesn't get correct flag.
I'm creating a C program with a server-client bases.
I've been trying to redirect the stdin to a named pipe I created and I've managed to put a client writing to the pipe. On the server side I opened the same pipe, closed stdin and redirected the stdin, using dup (tried with dup2 as well), to the pipe.
I have to read the input with the function getline. The problem is it reads the first input correctly, but recieves only nulls after it. I'll add a sample to the question.
server:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
main () {
char* str;
size_t size=0;
int pshell_in;
unlink("/tmp/par-shell-in");
if(mkfifo("/tmp/par-shell-in", 0777) < 0){
fprintf(stderr, "Error: Could not create pipe\n");
exit(-1);
}
if((pshell_in = open("/tmp/par-shell-in", O_CREAT | O_RDONLY, S_IRUSR)) < 0){
fprintf(stderr, "Error: Failed to open file\n");
exit(-1);
}
dup2(pshell_in, 0);
close(pshell_in);
while(1) {
if (getline(&str, &size, stdin)<0) {
printf("Oh dear, something went wrong with getline()! %s\n", strerror(errno));
return -1;
}
printf("%s", str);
}
}
* I know its null cause I've printed it with read (instead of redirecting) and it prints (null).
client:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#define VECTORSIZE 7
int main() {
char* buf;
int pshell_in;
size_t size=0;
if((pshell_in = open("/tmp/par-shell-in", O_WRONLY, S_IWUSR)) < 0){
fprintf(stderr, "Error: Failed to open file\n");
exit(-1);
}
printf("%d\n", pshell_in);
while(1) {
if (getline(&buf, &size, stdin) < 0) {
return -1;
}
write(pshell_in, buf, 256);
}
}
I suspect its right because if I use read on the client side (replacing O_WRONLY with O_RDWR) it prints the string as I typed it.
Can anyone help me with this one?
FIFOs are funny things. If a process tries to open one for reading, it will block until there's a process that opens it for writing. Conversely, if a process tries to open one for writingt, it will block until there's a process that opens it for reading. However, multiple processes can open it for reading or writing. When there are no more processes with it open for reading, writes will fail; when there are no more processes with it open for writing, reads will fail. And when the operations fail, you have to close and reopen the FIFO to continue processing data afresh.
I strongly suspect you're running into problems because of these behaviours.
Additionally, your client write code is dubious; you aren't paying any attention to how much data was read. You have:
while(1) {
if (getline(&buf, &size, stdin) < 0) {
return -1;
}
write(pshell_in, buf, 256);
}
If, as is probable, you read less than 256 characters of input in the line, then it's quite possible that you go writing beyond the bounds of the array that was allocated by getline(). It's also distinctly possible that some or even most of that data is null bytes. However, the (null) you're seeing in the server typically indicates that you're trying to print a string but passed printf() a null pointer. Whatever's going on, most of it is undefined behaviour which is a Bad Thing™ and should be avoided at all costs.
You should have something more like:
ssize_t nbytes;
while ((nbytes = getline(&buf, &size, stdin)) > 0)
{
if (write(pshell_in, buf, nbytes) != nbytes)
{
fprintf(stderr, "Short write to FIFO\n");
break;
}
}
free(buf);
Note how this only writes as much data as was read and doesn't assume that 256 bytes were available to be written.
I am trying to share a socket descriptor with another local process on the same Linux machine. These processes are "unrelated" i.e., they are not parent/child related and are not forked. They are independent. Ultimately, the flow I want is something like:
| [Process1]
| -> master_socket = socket()
| -> setsockopt(master_socket...)
| -> fcntl(master_socket...)
| -> bind(master_socket...)
| -> listen(master_socket...)
| -> Share master_socket with Process2
|
| [Process2]
| -> Receive and store master_socket
| -> Use select() on master_socket
| -> Use accept() on master_socket to receive connections...
Based on a few related threads, it seems as though this is possible using a Unix domain socket which will track that the socket handle was sent from Process1 to Process2 in the kernel, giving it permission (e.g., here, here, and here).
What I am trying to determine is whether or not the descriptor is possible to share over a POSIX message queue. Oddly enough, if I create the socket BEFORE opening the queue, it seems to work OK. However, if I create the socket AFTER opening the queue, the descriptor read on Process2 comes up as "invalid."
Example Programs
Here is a sample program that sends a socket descriptor via a message queue. If init_socket() is called before open_queue(), then the descriptor received is valid. If visa-versa then it comes across invalid.
send.c: gcc -o send send.c -lrt
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <syslog.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/fcntl.h>
#include <string.h>
#include <errno.h>
#include <mqueue.h>
int init_socket();
int open_queue();
mqd_t msgq_id;
int main() {
int socket;
char msg_str[16];
// HERE: ordering matters. If open_queue() is done before init_socket(), then
// the descriptor is received invalid. If init_socket() is called BEFORE open_queue()
// then the descriptor received is valid.
open_queue();
socket = init_socket();
// Put the socket on the queue
memset(msg_str, '\0', sizeof(msg_str));
snprintf(msg_str, sizeof(msg_str), "%d", socket);
if(mq_send(msgq_id, msg_str, strlen(msg_str)+1, 1) == -1) {
printf("Unable to send the message on the queue: %s\n", strerror(errno));
return -1;
}
}
int open_queue() {
// Create a queue to share the socket
if(msgq_id = mq_open("/share_socket", O_RDWR | O_CREAT | O_EXCL, S_IRWXU | S_IRWXG, NULL)==-1) {
if(errno != EEXIST) {
printf("Failed to create IPC queue: %s\n", strerror(errno));
return -1;
}
// Re-open the already existing queue.
if((msgq_id = mq_open("/share_socket", O_RDWR)) != -1) {
printf("Re-opened the IPC queue: %s\n", "/share_socket");
} else {
printf("Failed to re-open IPC queue %s: %s\n", "/share_socket", strerror(errno));
return -1;
}
}
return 1;
}
int init_socket() {
int master_socket;
int opt=1;
struct sockaddr_in loc_addr = { 0 };
// Create the high level master socket
if( (master_socket = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
printf("Unable to create master_socket\n");
return EXIT_FAILURE;
}
// Set socket to accept multiple connections
if( setsockopt(master_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 ) {
printf("Error setting socket to accept multiple connections\n");
return EXIT_FAILURE;
}
// Set the socket type
bzero(&loc_addr, sizeof(struct sockaddr_in));
loc_addr.sin_family = AF_INET;
loc_addr.sin_addr.s_addr = htonl(INADDR_ANY);
loc_addr.sin_port=htons(1200);
// Set the socket to nonblocking
if (fcntl(master_socket, F_SETFL, O_NDELAY) < 0) {
printf("Can't set socket to non-blocking\n");
return EXIT_FAILURE;
}
// Bind to the socket
if (bind(master_socket, (struct sockaddr *)&loc_addr, sizeof(loc_addr)) < 0) {
return EXIT_FAILURE;
}
// Now, listen for a maximum of 6 pending clients
if(listen(master_socket, 6) < 0) {
printf("Could not set the socket to listen\n");
close(master_socket);
return EXIT_FAILURE;
}
return master_socket;
}
read.c: gcc -o read read.c -lrt
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <syslog.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/fcntl.h>
#include <string.h>
#include <errno.h>
#include <mqueue.h>
#define MAX_MSG_LEN 10000
int main() {
mqd_t msgq_id;
int master_socket;
unsigned int sender;
int bytes;
char msgcontent[MAX_MSG_LEN];
// Re-open the already existing queue.
if((msgq_id = mq_open("/share_socket", O_RDWR)) != -1) {
printf("Re-opened the IPC queue: %s\n", "/share_socket");
} else {
printf("Failed to re-open IPC queue %s: %s\n", "/share_socket", strerror(errno));
return -1;
}
// Try to read from the queue.
if((bytes = mq_receive(msgq_id, msgcontent, MAX_MSG_LEN, &sender)) == -1)
{
// If the failure was due to there being no messages, just return 0.
if(errno==EAGAIN)
return 0;
printf("Unable to read from the queue\n");
return -1;
}
sscanf(msgcontent, "%d", &master_socket);
printf("Got master socket value: %d\n", master_socket);
if(master_socket != 0 && (fcntl(master_socket, F_GETFD) != -1 || errno != EBADF))
printf("... socket is valid\n");
else
printf("... SOCKET IS INVALID\n");
return 1;
}
How to run: Just go ahead and run ./read and it will wait on the message queue and then run ./send. If you compiled send.c with init_socket() before open_queue(), you will see:
$ ./read
Re-opened the IPC queue: /share_socket
Got master socket value: 3
... socket is valid
Otherwise:
$ ./read
Re-opened the IPC queue: /share_socket
Got master socket value: 4
... SOCKET IS INVALID
What would cause this behavior where the ordering is important?
Problem One:
Both programs will start with file descriptors 0, 1, & 2 open and valid.
When you run send with init_socket first the returned file descriptor for the socket witl be 3. Then you open the queue which will be 4. You send 3 to read process.
In read you open the queue which will be file descriptor 3. You read the queue and find you were sent a 3, which is actually the fd of the queue. So you are "testing" the queue file descriptor.
Conversely when in send you open the queue first and then the socket you are sending the file descriptor 4 to read. There is no file descriptor 4 open in read (the queue will still be opened as 3) so it naturally fails the "test".
Problem 2:
The test is wrong.
if (master_socket != 0 && (fcntl(master_socket, F_GETFD) != -1 || errno != EBADF))
printf("... socket is valid\n");
else
printf("... SOCKET IS INVALID\n");
All this is telling you is that it isn't file descriptor 0 and you can read the file descriptor flags. A test that the message queue file descriptor will pass.
A better test is something like this:
void isSocket(int fd)
{
struct stat statbuf;
if (fstat(fd, &statbuf) == -1)
{
perror("fstat");
exit(1);
}
if (S_ISSOCK(statbuf.st_mode))
printf("%d is a socket\n", fd);
else
printf("%d is NOT a socket\n", fd);
}
I haven't tested your pgms but if you print out all your file descriptors from both programs as you open them and try the above test it should bare out what I am saying.
I'm studying linux fifos and I made two small C programs which communicate through fifo. The first one acts like a server, it receive a pattern and executes a command using that pattern. The second one acts like a client, it sends the pattern and receive the result. I want the server to be capable of serving multiple requests, not necessarily simultaneously, but the weird thing is that after the first client is served it just stops although I put there an infinite loop.
server.c
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
void siginthandler(int i){
remove("./fifo1");
remove("./fifo2");
printf("Got SIGINT signal\n");
exit(EXIT_SUCCESS);
}
int main(int argc, char *argv[]){
signal(SIGINT, siginthandler);
int f = mkfifo("./fifo1", 0600);
if (f == -1){
perror("Unable to create fifo1\n");
exit(EXIT_FAILURE);
}
f = mkfifo("./fifo2", 0600);
if (f == -1){
perror("Unable to create fifo2\n");
exit(EXIT_FAILURE);
}
int fd1 = open("./fifo1", O_RDONLY);
int fd2 = open("./fifo2", O_WRONLY);
if (fd1 == -1 || fd2 == -1){
perror("Unable to open fifos\n");
exit(EXIT_FAILURE);
}
while (1){
char buf[50];
char pattern[50];
read(fd1, pattern, 50);
char command[80] = "ps -e | grep ";
strcat(command, pattern);
FILE *result = popen(command, "r");
while (fgets(buf, 50, result)){
write(fd2, buf, 50);
//printf("%s", buf);
}
memset((void *) buf, 0, 50);
write(fd2, buf, 50);
pclose(result);
}
remove("./fifo1");
remove("./fifo2");
return 0;
}
client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
int fd1 = open("./fifo1", O_WRONLY);
int fd2 = open("./fifo2", O_RDONLY);
if ((fd1 == -1) || (fd2 == -1)){
perror("Unable to find fifos");
exit(EXIT_FAILURE);
}
char input[50];
printf("Give pattern: ");
scanf("%s", input);
write(fd1, input, 50);
char buf[50];
while (read(fd2, buf, 50) == 50){
if (buf[0] == 0){
break;
}
printf("%s", buf);
}
return 0;
}
When the first client closes the FIFO, the server gets EOF on the FIFO, and continues to get no new data in perpetuity. The server has to reopen the FIFO for the next client. If there were multiple clients all with the FIFO open concurrently, the server would not get EOF until the last of the clients disconnected (as long as there is one writer, the reader — the server — will be OK).
This is expected behaviour — or, since you weren't expecting it, is the behaviour that should be expected.
Of course, since your code completely ignores the return value from read(), you have no idea what, if anything, is being read.
The code:
memset((void *) buf, 0, 50);
write(fd2, buf, 50);
is curious; why would you send a buffer of 50 0 bytes to the client? You could perfectly well close the FIFO without sending that.
Also note that writing on a FIFO where there isn't a reader will generate a SIGPIPE signal — and you aren't handling those. The default action for SIGPIPE is to exit.
Writing to a pipe gets you a SIGPIPE if there's no reader; you need to have the server open the pipe for reading, so there is a reader (which doesn't read anything, but it exists).
I tried searching on the net, but there are hardly any resources. A small example would suffice.
EDIT
I mean, two different C programs communicating with each other. One program should send "Hi" and the other should receive it. Something like that.
A regular pipe can only connect two related processes. It is created by a process and will vanish when the last process closes it.
A named pipe, also called a FIFO for its behavior, can be used to connect two unrelated processes and exists independently of the processes; meaning it can exist even if no one is using it. A FIFO is created using the mkfifo() library function.
Example
writer.c
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int fd;
char * myfifo = "/tmp/myfifo";
/* create the FIFO (named pipe) */
mkfifo(myfifo, 0666);
/* write "Hi" to the FIFO */
fd = open(myfifo, O_WRONLY);
write(fd, "Hi", sizeof("Hi"));
close(fd);
/* remove the FIFO */
unlink(myfifo);
return 0;
}
reader.c
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#define MAX_BUF 1024
int main()
{
int fd;
char * myfifo = "/tmp/myfifo";
char buf[MAX_BUF];
/* open, read, and display the message from the FIFO */
fd = open(myfifo, O_RDONLY);
read(fd, buf, MAX_BUF);
printf("Received: %s\n", buf);
close(fd);
return 0;
}
Note: Error checking was omitted from the above code for simplicity.
From Creating Pipes in C, this shows you how to fork a program to use a pipe. If you don't want to fork(), you can use named pipes.
In addition, you can get the effect of prog1 | prog2 by sending output of prog1 to stdout and reading from stdin in prog2. You can also read stdin by opening a file named /dev/stdin (but not sure of the portability of that).
/*****************************************************************************
Excerpt from "Linux Programmer's Guide - Chapter 6"
(C)opyright 1994-1995, Scott Burkett
*****************************************************************************
MODULE: pipe.c
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
int main(void)
{
int fd[2], nbytes;
pid_t childpid;
char string[] = "Hello, world!\n";
char readbuffer[80];
pipe(fd);
if((childpid = fork()) == -1)
{
perror("fork");
exit(1);
}
if(childpid == 0)
{
/* Child process closes up input side of pipe */
close(fd[0]);
/* Send "string" through the output side of pipe */
write(fd[1], string, (strlen(string)+1));
exit(0);
}
else
{
/* Parent process closes up output side of pipe */
close(fd[1]);
/* Read in a string from the pipe */
nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
printf("Received string: %s", readbuffer);
}
return(0);
}
dup2( STDIN_FILENO, newfd )
And read:
char reading[ 1025 ];
int fdin = 0, r_control;
if( dup2( STDIN_FILENO, fdin ) < 0 ){
perror( "dup2( )" );
exit( errno );
}
memset( reading, '\0', 1025 );
while( ( r_control = read( fdin, reading, 1024 ) ) > 0 ){
printf( "<%s>", reading );
memset( reading, '\0', 1025 );
}
if( r_control < 0 )
perror( "read( )" );
close( fdin );
But, I think that fcntl can be a better solution
echo "salut" | code
What one program writes to stdout can be read by another via stdin. So simply, using c, write prog1 to print something using printf() and prog2 to read something using scanf(). Then just run
./prog1 | ./prog2
Here's a sample:
int main()
{
char buff[1024] = {0};
FILE* cvt;
int status;
/* Launch converter and open a pipe through which the parent will write to it */
cvt = popen("converter", "w");
if (!cvt)
{
printf("couldn't open a pipe; quitting\n");
exit(1)
}
printf("enter Fahrenheit degrees: " );
fgets(buff, sizeof (buff), stdin); /*read user's input */
/* Send expression to converter for evaluation */
fprintf(cvt, "%s\n", buff);
fflush(cvt);
/* Close pipe to converter and wait for it to exit */
status=pclose(cvt);
/* Check the exit status of pclose() */
if (!WIFEXITED(status))
printf("error on closing the pipe\n");
return 0;
}
The important steps in this program are:
The popen() call which establishes the association between a child process and a pipe in the parent.
The fprintf() call that uses the pipe as an ordinary file to write to the child process's stdin or read from its stdout.
The pclose() call that closes the pipe and causes the child process to terminate.
This answer might be helpful for a future Googler.
#include <stdio.h>
#include <unistd.h>
int main(){
int p, f;
int rw_setup[2];
char message[20];
p = pipe(rw_setup);
if(p < 0){
printf("An error occured. Could not create the pipe.");
_exit(1);
}
f = fork();
if(f > 0){
write(rw_setup[1], "Hi from Parent", 15);
}
else if(f == 0){
read(rw_setup[0],message,15);
printf("%s %d\n", message, r_return);
}
else{
printf("Could not create the child process");
}
return 0;
}
You can find an advanced two-way pipe call example here.
First, have program 1 write the string to stdout (as if you'd like it to appear in screen). Then the second program should read a string from stdin, as if a user was typing from a keyboard. then you run:
$ program_1 | program_2