I'm trying to send a bi-dimensional array from a child process to a parent process and failing terribly. Not exactly sure how this should be done but here's what I tried.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int fd[2];
int matrix[2][2];
int main () {
pipe (fd);
if (0 == fork()) {
printf ("Start child process with pid: %d\n", getpid());
for (int i = 0; i < 2; i++)
matrix[i][i] = 1;
write (fd[1], matrix, 4);
exit (0);
}
printf ("Start parent process with pid: %d\n", getpid());
read (fd[0], matrix, 4);
printf ("Received %d\n", matrix[1][1]);
return 0;
}
Compiles correctly but the received value is always 0 instead of 1.
What am I doing wrong ? (lots of things, I expect)
It's because you are misunderstanding the third argument of read and write
to be number of elements. read and write system calls require their third argument to be count of bytes.
Change your code
write (fd[1], matrix, 4);
...
read (fd[0], matrix, 4);
to
write (fd[1], matrix, 4*sizeof(int));
...
read (fd[0], matrix, 4*sizeof(int));
Related
I am trying to write a program so that the parent and child process can communicate back and forth between each other. The parent process and the child process ought to print the values from 1-100 where each process prints the value incrementing it by 1 each time. Now the issue I face is that, I know nothing much about pipes. What I gather from reading materials online is that I can use a pipe to read and write values. I have leveraged this to print something in the child process, and send back something to the parent. Now, I am not sure how to get the parent to return to the child after printing for itself? I know my code is probably all wrong, but I am really not sure what I should do.
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, const char * argv[]) {
int fd[2];
if (pipe(fd)== -1){
printf("An error occured while opening the pipe\n");
}
int id = fork();
int i = 0;
if (id == 0){
close(fd[0]);
printf("In child: %d", i);
i ++;
write(fd[1], &i, sizeof(int));
close(fd[1]);
} else {
wait(NULL);
close(fd[1]);
int y;
read(fd[0],&y, sizeof(int));
close(fd[0]);
}
}
To keep it simple, it's up to you to check return values and handle errors. This will only do it between 0 - 9 and you will have to expand the mathematics.
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
int pipefd_1[2];
int pipefd_2[2];
pid_t cpid;
pipe(pipefd_1);
pipe(pipefd_2);
cpid = fork();
if (cpid == 0) { /* Child reads from pipe 1, writes to pipe 2*/
char cval[] = {'0'};
close(pipefd_1[1]); /* Close unused write and read ends */
close(pipefd_2[0]);
while (atoi(cval) != 9) {
read(pipefd_1[0], cval, 1);
printf("Child print %d\n", atoi(cval));
cval[0] += 1;
write(pipefd_2[1], cval, 1);
}
} else {
char cval[] = {'0'}; /* Parent writes buf to pipe 1 */
close(pipefd_1[0]); /* Close unused read end */
close(pipefd_2[1]);
while (atoi(cval) != 9) {
write(pipefd_1[1], cval, 1);
read(pipefd_2[0], cval, 1);
printf("Parent print %d\n", atoi(cval));
cval[0] += 1;
}
}
}
Output
I am trying to write a program that initializes an integer in the parent and then in the first fork() we take that value increment it and pass it along the tube to the next process called by the current child. This goes on for 2 more times. My problem is that I initiate the integer to 96 and ideally since we have 3 processes the program should return 99. But instead, it returns 'a', which means it has only incremented once.
This is my code:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
int main(int argc, char **argv)
{
int status;
int i;
int pipes[4];
pipe(pipes);
pipe(pipes + 2);
int num = 96;
if (fork() == 0)
{
dup2(pipes[1], 1);
close(pipes[0]);
close(pipes[1]);
close(pipes[2]);
close(pipes[3]);
num++;
write(pipes[1], &num, sizeof(int));
}
else
{
if (fork() == 0)
{
dup2(pipes[0], 0);
dup2(pipes[3], 1);
close(pipes[0]);
close(pipes[1]);
close(pipes[2]);
close(pipes[3]);
read(pipes[0], &num, sizeof(int));
num++;
write(pipes[3], &num, sizeof(int));
}
else
{
if (fork() == 0)
{
dup2(pipes[2], 0);
close(pipes[0]);
close(pipes[1]);
close(pipes[2]);
close(pipes[3]);
read(pipes[2], &num, sizeof(int));
num++;
write(1, &num, sizeof(int));
}
}
}
close(pipes[0]);
close(pipes[1]);
close(pipes[2]);
close(pipes[3]);
for (i = 0; i < 3; i++)
wait(&status);
}
How do I make it so that an integer is printed?
Why does my increment work only once?
You close(pipe[0]) and then try to read from it. Read from the dup'd fd instead. You would notice this error if you checked the values returned from read and write.
To print an integer, use printf("%d", num) instead of write. The reason num increments only once is that the read in the final child fails and does not change num, so after the read num retains the value it had when it was initialized.
All you need to do is either remove the close calls from inside the conditions (all of the pipes get closed twice in the current code (or, more accurately, they are closed once and then a second attempt to close them fails, but the failure goes unnoticed)) or read/write from/to the dup'd fd.
I am doing this homework for some time and it's giving me a headache.
Write a program that writes the integer “i+1” into element “i” of a table of MAXBUF
integers (for every element of the table). MAXBUF should be initially “#define”d as 10 in the source
code of the program. Then, using only one write() operation, the program should write the entire
table of integers in binary format into an initially truncated file, named “filetable.bin”. In the next
step the program should create a child process, and then print the message “The parent process
is terminating.”, and then exit. The child process should separately read, in binary format, from
the file each integer in the same order as the integers are stored in the file, and print each such
integer to the standard output. In the final step of the program, the child process should wait for its
parent process to terminate, and then print to the standard output the message “The child process
is terminating.”, and then terminate. All the operations on the “filetable.bin” file should be
performed using system calls.
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#define MAXBUF 10
int decimalToBinary(int n);
int main(int argc, char *argv []) {
int i, fd, n, status, childpid;
char buffer[MAXBUF];
pid_t pid = (long)getpid();
fd = open("filetable.bin", O_CREAT | O_RDWR);
for(i=0; i<MAXBUF; i++) {
n=i+1;
buffer[i] = decimalToBinary(n);
}
write(fd,buffer,sizeof(buffer));
childpid = fork();
if(childpid >0) {
printf("The parent process terminating.\n");
exit(0); // or kill(pid, SIGKILL)
}
if(childpid < 0) {
perror("Failed to fork\n");
}
else {
read(fd,&childpid,sizeof(childpid));
write(STDOUT_FILENO,&childpid,sizeof(childpid));
wait(&status);
printf("The child process is terminating\n");
exit(1);
}
return(0);
}
int decimalToBinary(int n) {
int remainder, binary=0, i=1;
while(n!=0) {
remainder = n%2;
n = n/2;
binary = binary + (remainder*i);
i = i*10;
}
return binary;
}
My problem is how do I read from the childpid and write with it in STDOUT?
EDIT: It appears in the output: "The parent process is terminating\n" "The child process is terminating\n". It's missing the STDOUT
I am working on a program that will take an integer and create two processes, a parent and a child. The parent will subtract 5 from the integer, pass it to the child who will divide it by 5, and then they will repeat this process 5 times, each time printing the current value of the integer.
The integer can be passed through a text file and be both written and read off of, or a pipeline can be used which ever is simpler.
I have been looking up the systems calls needed, and have a semi working program. I have been stuck for hours however, and I think my issue is that I can't get them to wait for each other to finish because my output is incorrect.
Here is what I got so far.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <ctype.h>
#include <fcntl.h>
int main(void)
{
int x=19530;
int w=1;
int fd[2];
pipe(fd);
int pid = fork();
int k;
for (k=0; k<5; k++) {
if (pid>0) {
//int x = 19530;
if ((close(fd[0]))==-1) {
perror("Close:");
}
read(fd[0], &x, sizeof(int));
x=x-5;
write (fd[1], &x, sizeof(int));
printf("X in parent %d\n", x);
close(fd[1]);
close(fd[0]);
} else if (pid==0) {
if ((close(fd[1]))==-1) {
perror("Close:");
}
read(fd[0], &x, sizeof(int));
x=x/5;
printf("X in child %d\n", x);
write (fd[1], &x, sizeof(int));
close(fd[1]);
close(fd[0]);
}
}
return 0;
}
However my output is an issue, I am getting:
X in parent 19525
X in child 3905
Close:: Bad file descriptor
X in parent 19520
Close:: Bad file descriptor
X in parent 19515
Close:: Bad file descriptor
X in parent 19510
Close:: Bad file descriptor
X in parent 19505
Close:: Bad file descriptor
X in child 781
Close:: Bad file descriptor
X in child 156
Close:: Bad file descriptor
X in child 31
Close:: Bad file descriptor
X in child 6
It seems to start off well, but then the child doesn't pass back properly then the parent runs too many times in a row before the child catches up. I also been trying to fix that bad file descriptor but to no avail.
Any help would be greatly appreciated.
Thanks.
#include <stdio.h>
#include <unistd.h>
#include <err.h>
#define ok(x) ({ int i_ = (x); if (i_ == -1) err(1, #x); i_; })
enum { p_, c_ }; // parent, child
enum { r_, w_ }; // read, write
int main(void)
{
int x = 19530;
int fd[2][2];
int pid;
ok(pipe(fd[0]));
ok(pipe(fd[1]));
ok(pid = fork());
close(fd[p_][pid ? r_ : w_]);
close(fd[c_][pid ? w_ : r_]);
for (int i = 0; i < 5; i++) {
if (pid) {
x -= 5;
printf("X in parent %d\n", x);
ok(write(fd[p_][w_], &x, sizeof(x)));
ok(read(fd[c_][r_], &x, sizeof(x)));
}
else {
ok(read(fd[p_][r_], &x, sizeof(x)));
x /= 5;
printf("X in child %d\n", x);
ok(write(fd[c_][w_], &x, sizeof(x)));
}
}
return 0;
}
Pipes are unidirectional, so you need two. I used some enums to try and make things easier to read.
I am having serious trouble working with pipes in C. I'm supposed to take in arguments from the command line (example: ./myprogram 123 45 67), read the arguments one character at a time into a buffer, send the character to the child process to be counted, and then return the total number of characters read to the parent process. My code is as follows(note: the comments are what I'm supposed to be doing):
// Characters from command line arguments are sent to child process
// from parent process one at a time through pipe.
// Child process counts number of characters sent through pipe.
// Child process returns number of characters counted to parent process.
// Parent process prints number of characters counted by child process.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
static int toChild[2];
static int fromChild[2];
static char buffer;
int main(int argc, char **argv)
{
int status;
int nChars = 0;
pid_t pid;
pipe(toChild);
pipe(fromChild);
if ((pid = fork()) == -1) {
printf("fork error %d\n", pid);
return -1;
}
else if (pid == 0) {
close(toChild[1]);
close(fromChild[0]);
// Receive characters from parent process via pipe
// one at a time, and count them.
int count = 0;
printf("child about to read\n");
while(read(toChild[0], &buffer, 1)){
count++;
}
// Return number of characters counted to parent process.
write(fromChild[1], &count, sizeof(count));
close(toChild[0]);
close(fromChild[1]);
printf("child exits\n");
}
else {
close(toChild[0]);
close(fromChild[1]);
// -- running in parent process --
printf("CS201 - Assignment 3 - Chris Gavette\n");
write(toChild[1], &argv[1], 1);
// Send characters from command line arguments starting with
// argv[1] one at a time through pipe to child process.
read(fromChild[0], &nChars, 1);
// Wait for child process to return. Reap child process.
// Receive number of characters counted via the value
// returned when the child process is reaped.
close(toChild[1]);
close(fromChild[0]);
waitpid(pid, &status, 0);
printf("child counted %d chars\n", nChars);
printf("parent exits\n");
return 0;
}
}
The child process seems to hang even though I've closed both ends of both pipes.
For starters, this is wrong.
write(toChild[1], &count, 1)
It will eventually contribute to your problem. count is a int, not char or unsigned char. You need to send sizeof(count). Also, the read-function upon hitting an error will return EOF, which is non-zero, so your child exit condition is not appropriate. it should look something like this:
while(read(toChild[0], &buffer, 1) == 1)
Finally, your parent process should cycle through each argument in argv[] sending each as a strlen sized buffer.
I'm nearly certain this is what you're trying to do. Note that in order to maintain sanity in knowing which descriptor is used for a specific purpose, I prefer using a #define to note what each process uses for reading and writing. This can be extended to any number of processes, btw, which I'm sure is not too far down the line for your next assignment:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
// P0_READ - parent read source
// P0_WRITE - parent write target
// P1_READ - child read source
// P1_WRITE - child write target
#define P0_READ 0
#define P1_WRITE 1
#define P1_READ 2
#define P0_WRITE 3
#define N_PIPES 4
int main(int argc, char **argv)
{
int fd[N_PIPES], count = 0, i;
pid_t pid;
char c;
if (pipe(fd) || pipe(fd+2))
{
perror("Failed to open pipe(s)");
return EXIT_FAILURE;
}
// fork child process
if ((pid = fork()) == -1)
{
perror("Failed to fork child process");
return EXIT_FAILURE;
}
// child process
if (pid == 0)
{
// close non P1 descriptors
close(fd[P0_READ]);
close(fd[P0_WRITE]);
// get chars from input pipe, counting each one.
while(read(fd[P1_READ], &c, 1) == 1)
count++;
printf("Child: count = %d\n", count);
write(fd[P1_WRITE], &count, sizeof(count));
// close remaining descriptors
close(fd[P1_READ]);
close(fd[P1_WRITE]);
return EXIT_SUCCESS;
}
// parent process. start by closing unused descriptors
close(fd[P1_READ]);
close(fd[P1_WRITE]);
// send each arg
for (i=1; i<argc; ++i)
write(fd[P0_WRITE], argv[i], strlen(argv[i]));
// finished sending args
close(fd[P0_WRITE]);
// Wait for child process to return.
wait(NULL);
// wait for total count
if (read(fd[P0_READ], &count, sizeof(count)) == sizeof(count))
printf("Parent: count = %d\n", count);
// close last descriptor
close(fd[P0_READ]);
return 0;
}
Input
./progname argOne argTwo
Output
Child: count = 12
Parent: count = 12
Edit: Single Pipe with Child Return Status
It seems from the comments of the original question your assignment may call for reaping the return status of the child process as the result count rather than returning it in a pipe. In doing so, you can do this with a single pipe-descriptor pair. I prefer the first method, but this works as well:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
// P0_WRITE - parent write target
// P1_READ - child read source
#define P1_READ 0
#define P0_WRITE 1
#define N_PIPES 2
int main(int argc, char **argv)
{
int fd[N_PIPES], count = 0;
pid_t pid;
char c;
if (pipe(fd))
{
perror("Failed to open pipe(s)");
return EXIT_FAILURE;
}
// fork child process
pid = fork();
if (pid == -1)
{
perror("Failed to fork child process");
return EXIT_FAILURE;
}
if (pid == 0)
{
// close non P1 descriptors
close(fd[P0_WRITE]);
// Return number of characters counted to parent process.
while(read(fd[P1_READ], &c, 1) == 1)
++count;
close(fd[P1_READ]);
printf("Child: count = %d\n", count);
return count;
}
// parent process. start by closing unused descriptors
close(fd[P1_READ]);
// eacn each arg entirely
for (int i=1; i<argc; ++i)
write(fd[P0_WRITE], argv[i], strlen(argv[i]));
// finished sending args
close(fd[P0_WRITE]);
// Wait for child process to return.
if (wait(&count) == -1)
{
perror("Failed to wait for child process");
return EXIT_FAILURE;
}
printf("Parent: count = %d\n", WEXITSTATUS(count));
return 0;
}
The results are the same, but note this is a biach to to debug as most debuggers will signal-trip on your child process and the real exit status is lost. On my Mac, for example, running this under Xcode trips:
Failed to wait for child process: Interrupted system call
while running from the command line gives:
Child: count = 12
Parent: count = 12
One of the many reasons I prefer the two-pipe methodology.