how to Pass the elements in a structure to an unamed pipe? - c

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
struct msg
{
int pid;
int giffs;
int curr;
};
main()
{
struct msg send = {1, 2, 3};
int p[2], pid, i;
char inbuff[sizeof(send)];
char *q;
pipe(p);
pid = fork();
if(pid > 0)
{
write(p[1], (char *)&send, sizeof(send));
printf("%ld \n", sizeof(send));
}
else
{
read(p[0], inbuff, sizeof(send));
printf("%s\n", inbuff);
}
}
The problem is the elements in the structure are not appearing at the read end,
could anyone please check on this. we can pass a string to a pipe, but I need to pass the bunch of integers to the pipe.

The bytes get read at the receiving end, but you try to print binary data as a string.
Treat the read bytes as struct msg instead:
else
{
struct msg received;
read(p[0], &received, sizeof(received));
printf("%d, %d, %d\n", received.pid, received.giffs, received.curr);
}

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
struct msg {
int pid;
int giffs;
int curr;
};
main()
{
struct msg send = {1, 2, 3};
int p[2], pid, i;
int *inbuff;
char *q;
pipe(p);
pid= fork();
if(pid > 0) {
write(p[1], (char *)&send, sizeof(send));
printf("%ld \n", sizeof(send));
sleep(1);
} else {
read(p[0],(char *) inbuff, sizeof(send));
for (i=0;i<sizeof(send)/sizeof(int);i++){
printf("%d\n", *inbuff++);
}
}
}
try this code..........
here make sure you use waitpid() instead of sleep so that parent process waits for child procees to terminate or else you will get inappropriate response...........

Related

how to synchronize two process

Hello I'm struggling right now with C language and process so basically I've just learnt about pipe and I want to use them just to exercise myself on it, so I want to try a code that basically use two child and 1 father, by one child the user enter some number then this child send those numbers to the other child and then this second child send them to the father who show them.
here my code so far
`
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <limits.h>
#include <string.h>
int main(int argc, char const *argv[])
{
pid_t son1;
pid_t son2;
int Pipe1[2];
int pipe2[2];
int sent=0;
int sent2=0;
int recive=0;
int recive2=0;
int j=0;
int mem[3];
if (pipe(Pipe1)==-1)
{
printf("error pipe1");
exit(0);
}
if (pipe(pipe2)==-1)
{
printf("error pipe2");
exit(0);
}
son1=fork();
if (son1==0)
{
close(Pipe1[0]);
//close(pipe2[0]);
//close(pipe2[1]);
printf("i'am the child 1\n");
for (int i = 0; i < 3; i++)
{
printf("type your number \n");
scanf("%d",&sent);
write(Pipe1[1],&sent,sizeof(int));
}
close(Pipe1[1]);
}
son2=fork();
if (son2==0)
{
close(Pipe1[1]);
close(pipe2[0]);
printf("i'am the son number 2 \n");
recive=read(Pipe1[0],&sent,sizeof(int));
while(recive == sizeof(int))
{
printf("nb reçu %d \n",sent);
mem[j]=sent;
recive= read(Pipe1[0],&sent,sizeof(int));
j++;
}
close(Pipe1[0]);
for (int p = 0; p < 3; p++)
{
sent2=mem[p];
printf("sent2 %d",sent2);
write(pipe2[1],&sent2,sizeof(int));
}
close(pipe2[1]);
when i run this code it does work but not how i expect, the commmunication between children work but not between child 2 and the father actualy if you look at the second part of the code of son2 "mem[]" value is not the same before close(pipe[1]) and after and this is why the comunication is mestup but i realy dont know how the value can change.. if someone can explain me it will be really kind of him
`
You create two pipes in the parent which are shared with the children, and the children do not share a pipe with each other. The easiest thing is probably to move the 2nd pipe to the child and have it fork the 2nd child:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void) {
int parent_child[2];
if(pipe(parent_child) == -1) {
printf("pipe failed\n");
exit(1);
}
if(!fork()) {
close(parent_child[0]);
int child_grand_child[2];
if(pipe(child_grand_child) == -1) {
printf("pipe failed\n");
exit(1);
}
printf("child write\n");
write(child_grand_child[1], "1", 1);
if(!fork()) {
char buf[1];
ssize_t n = read(child_grand_child[0], buf, sizeof buf);
printf("grand child read\n");
write(parent_child[1], buf, n);
exit(0);
}
close(parent_child[1]);
wait(&(int) {0});
exit(0);
}
close(parent_child[1]);
char buf[1];
ssize_t n = read(parent_child[0], buf, sizeof buf);
printf("parent read %*s\n", n, buf);
wait(&(int) {0});
}
which outputs:
child write
grand child read
parent read 1

Sending int through shared memory between two processes

I would like to send an int from one process to another through shared memory.
I tried simply placing the value of the int into the shared memory (&number) - didnt work.
I tired casting the string to bytes into a char array (memcpy) and reading a sizeof(int) from the other process - didn't work.
i tired memcpy the value of the int into a char array, sending it to the other process, copying back it with memcpy : from the char array into an int - didn't work
My last attempt is this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/stat.h> // S_IRUSR
int main(int argc, char *argv[])
{
pid_t gyerek;
key_t kulcs;
int oszt_mem_id;
char *s;
kulcs = ftok(argv[0], 1);
oszt_mem_id = shmget(kulcs, 500, IPC_CREAT | S_IRUSR | S_IWUSR);
s = shmat(oszt_mem_id, NULL, 0);
gyerek = fork();
if (gyerek == 0)
{
//printf("Child read this: %s\n", s);
char szamarr[10];
int szam = 12;
memcpy(&szamarr, &szam, sizeof(int));
strcpy(s, szamarr);
sleep(1);
strcpy(s, &szam);
sleep(3);
shmdt(s);
}
else
{
sleep(2);
int szam;
char szamarr[10];
memcpy(&szamarr, &s, sizeof(int));
printf("Parent read this: %s\n", szamarr);
sleep(1);
int szam2 = (int) s;
printf("Parent read this: %s\n", s);
shmdt(s);
wait(NULL);
shmctl(oszt_mem_id, IPC_RMID, NULL);
}
}
The result is either a random number and nothing
You don't need to involve strings if you only want to pass an int. However generally, it's easier to use structures for this kind of communication:
typedef struct {
int szam;
// ...
} mystruct_t;
int main(int argc, char *argv[])
{
pid_t gyerek;
key_t kulcs;
int oszt_mem_id;
char *s;
kulcs = ftok(argv[0], 1);
oszt_mem_id = shmget(kulcs, sizeof(mystruct_t), IPC_CREAT | S_IRUSR | S_IWUSR);
s = shmat(oszt_mem_id, NULL, 0);
gyerek = fork();
if (gyerek == 0) // child
{
mystruct_t ms={0};
ms.szam = 12;
memcpy(s, &ms, sizeof(mystruct_t));
sleep(3);
shmdt(s);
}
else // parent
{
sleep(1);
mystruct_t ms={0};
memcpy(&ms, s, sizeof(mystruct_t));
printf("Parent read this: %d\n", ms.szam);
shmdt(s);
wait(NULL);
shmctl(oszt_mem_id, IPC_RMID, NULL);
}
}

kill() function not working in C language

I have the following code. It generates n child and then a random number between 0 and n. So that random number lets suppose is "i". The child number i must kill his brothers.
The problem is that the kill function is not killing anything since both ptree after and before are exactly the same.
I cant found a solution, the output must be the father and the i child only since all his brothers were killed by him.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#include <math.h>
char archSalidaAntes[] = "aprocesosAntes.txt";
char archSalidaDespues[] = "aprocesosDespues.txt";
void imprimirArreglo(int arr[], int n){
int i;
for(i=0; i<n; i++){
printf("%d\t", arr[i]);
}
printf("\n");
}
void imprimirArbolTxt(char nombreArchivo[], pid_t id){
char buff[255];
sprintf(buff, "pstree -p -c -l %d > %s", (int)id, nombreArchivo);
system(buff);
}
void communicateSon(int arrProc[], int n, int fd[]){
int i;
int data;
int writeResp;
close(fd[0]); //closing input
for(i=0; i<n; i++){
data = arrProc[i];
writeResp = write(fd[1], &data, sizeof(data));
if(!writeResp){
printf("error writing");
}
}
close(fd[1]); //closing output
}
void killOthers(int n, int fd[], int randInt){
int i;
int readResp;
int killResp;
int data;
int arrProc[n];
close(fd[1]); //closing output
i = 0;
while(1){
readResp = read(fd[0], &data, sizeof(data));
fflush(stdout);
fflush(stdin);
if(!readResp){
break;
}
arrProc[i] = data;
i++;
}
imprimirArreglo(arrProc, n);
printf("id elegido: %d\n", getpid());
for(i=0; i<n; i++){
if(i!= randInt){
printf("killing: %d\n", arrProc[i]);
killResp = kill((pid_t)arrProc[i], SIGKILL);
if(killResp < 0){
printf("error kill: %d \n", killResp);
}
int aux = kill(arrProc[i], 0);
printf("aux: %d\n", aux);
}
}
close(fd[0]); //closing input
char com[30];
sprintf(com, "pstree -p %d", getppid());
system(com);
}
int main(int argc, char **argv){
int n;
int i;
int *arrProc;
int randInt;
int fd[2];
pid_t pId;
n = atoi(argv[1]);
printf("n = %d\n", n);
srand(time(NULL));
arrProc = (int*) malloc(sizeof(int) * n);
randInt = rand() % n;
pipe(fd);
for(i=0; i<n; i++){
pId = fork();
if(pId){
arrProc[i] = (int)pId;
if(i == (n-1)){
char com[30];
sprintf(com, "pstree -p %d", getppid());
system(com);
communicateSon(arrProc, n, fd);
waitpid(arrProc[randInt], NULL, 0);
printf("termino la espera del hijo\n");
free(arrProc);
}
} else if(pId == 0){ //hijos
if(i==randInt){
killOthers(n, fd, randInt);
exit(0);
} else{
break;
}
}
}
sleep(0.5);
return 0;
}
Since main process never calls waitpid for other children all of them become zombies after getting killed.
Update: you should also close pipe ends descriptors in other child processes prior to putting them to sleep, otherwise killer child process will get stuck at waiting for more data to come from the pipe.
} else{
close(fd[0]);
close(fd[1]);
break;
}
Update: sleep takes unsigned int number of seconds, so sleep(0.5) will be equivalent to sleep(0).
Try with sleep(1).
The sleep() function wants an integer argument, so sleep(0.5) equals to zero - which is probably not "long enough" for your demo to work. The child processes may terminate before the kill signal can reach them.

individual char extraction in c while using messages and msgsnd

This is bugging me for days.
The problem is my not so good understanding of pointers and addresses in c so i hope someone will be able to help me out.
I need to pass some strings as input parameters and create as much producer processes + one consumer process.
Producers should take the string apart and send each letter as message to queue. At the end it should send NULL("").
The consumer should wait for messages and print them out.
The whole code and output is below. By looking at the output i'd say that the problem is somewhere in the producer. To be more precise it is in the first line of te for loop but i can not get it right.
manager.c - This is the main program that operates processes
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/msg.h>
int main( int argc, char *argv[], char *envp[] ) {
printf("Starting %d processes \n", argc);
putenv("MSG_KEY=12345");
for (int i = 1; i < argc; i++) {
printf("argv[%d] = %s \n", i, argv[i]);
pid_t producer = fork();
if (producer == 0) {
printf("producer pid - %d\n", getpid());
execl("./producer", "producer", argv[i], NULL);
}
}
pid_t consumer = fork();
if (consumer == 0) {
printf("consumer pid - %d\n", getpid());
execl("./consumer", "consumer", NULL);
exit(0);
} else {
printf("manager pid - %d\n", getpid());
wait(NULL);
}
int status;
while(waitpid(consumer, &status, 0) == -1);
printf("DONE consumer\n");
printf("DONE manager\n");
return 0;
}
producer.c
/*
** writes to message queue
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct my_msgbuf {
long mtype;
char mtext[1];
};
int main( int argc, char *argv[], char *envp[] ) {
struct my_msgbuf buf;
int msqid;
key_t key = atoi(getenv("MSG_KEY"));
if ((msqid = msgget(key, 0600 | IPC_CREAT)) == -1) {
perror("msgget");
exit(1);
}
buf.mtype = getpid();
// I believe the error is in this for loop or to be more precise in the first line of the for loop.
// takes the first argument and sends characters in separate messages
for (int i = 0; i < strlen(argv[1]); ++i) {
char c = argv[1][i];
strcpy(buf.mtext, &c);
printf ("Sending -%s-\n", buf.mtext);
if (msgsnd(msqid, (struct msgbuf *)&buf, strlen(buf.mtext)+1, 0) == -1)
perror("msgsnd");
}
// send NULL at the end
memcpy(buf.mtext, "", strlen("")+1);
if (msgsnd(msqid, (struct msgbuf *)&buf, strlen("")+1, 0) == -1)
perror("msgsnd");
return 0;
}
consumer.c
/*
** reads from message queue
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct my_msgbuf {
long mtype;
char mtext[1];
};
int main( int argc, char *argv[], char *envp[] ) {
struct my_msgbuf buf;
int msqid;
key_t key = atoi(getenv("MSG_KEY"));
if ((msqid = msgget(key, 0600 | IPC_CREAT)) == -1) {
perror("msgget");
exit(1);
}
int flag = 0;
int wait_counter = 0;
while (wait_counter < 10) {
msgrcv(msqid, (struct msgbuf *)&buf, sizeof(buf)-sizeof(long), 0, flag);
if (errno == ENOMSG){
wait_counter++;
printf ("Sleaping for one second...zzzZZZzzz...%d\n", wait_counter);
usleep(1000 * 1000);
} else {
printf("Received:\n\ttype: -%ld- \n\tchar: -%s- \n", buf.mtype, buf.mtext);
int compare = strcmp(buf.mtext, "");
if(compare == 0){
printf("NULL received\n");
flag = IPC_NOWAIT;
} else {
flag = 0;
}
wait_counter = 0;
}
errno = 0;
}
if (msgctl(msqid, IPC_RMID, NULL) == -1) {
perror("msgctl");
exit(1);
} else {
printf("Message queue removed\n");
}
return 0;
}
Output - i have to give you the screenshot here because c/p deletes the problem and everything looks ok
Any help will be much appreciated! Thank you!
Error when used as suggested in the #sergeya answer below
*buf.mtext = c;
Your problem (one of them, at least) is here:
char c = argv[1][i];
strcpy(buf.mtext, &c);
strcpy() will try to copy as many characters as there are until nul-terminator '\0' is encountered, starting from c. You need to copy one character exactly, so you just need
*buf.mtext = c;
As i said, the problem was in the producer inside the for loop. I will put the change here. Hope it helps anyone with the similar problem.
#SergeyA gave me excellent clue where the problem is so i switched from "strcpy" to "memcpy" and i have copied just the first character and not the nul-terminator.
Also i have changed the "strlen" to "sizeof" and removed the +1.
Producer.c
...
for (int i = 0; i < strlen(argv[1]); ++i) {
char c = argv[1][i];
memcpy(buf.mtext, &c, sizeof(&c)+1);
printf ("Sending -%c-\n", buf.mtext);
if (msgsnd(msqid, (struct msgbuf *)&buf, sizeof(buf.mtext), 0) == -1)
perror("msgsnd");
}
...

2 way pipe communication. cant spend from child

I can't get this basic communication to work.
All I want to do, is send information via the child's stdout to the parents file descriptor.
I am getting a seg fault.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define READ 0
#define WRITE 1
int main(void){
int fdRead[2];
int pid, i, num;
FILE* output;
char mystring [100];
char c;
pid = fork();
if(pid){
FILE * read;
close(fdRead[WRITE]);
read = fdopen(fdRead[READ], "r");
fgets(mystring,100, read);
printf("parent %d",mystring );
} else {
/* child */
dup2(fdRead[WRITE], STDOUT_FILENO);
close(fdRead[READ]);
close(fdRead[WRITE]);
printf("child" );
}
exit(0);
}
Your code does nothing about pipe.
Code for communicating between parent and child processes using pipe looks as follows
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define READ 0
#define WRITE 1
int main(void){
int pipefd[2];
pid_t pid;
int i, num;
if (pipe(pipefd)<0) { /* create pipe */
perror("pipe");
exit(-1);
}
char mystring [100];
char c;
pid = fork();
if(pid<0){
perror("fork");
exit(-1);
} else if (pid=1) { /* parent */
char *mystring = "message to child";
write(pipefd[WRITE],mystring,strlen(mystring);
sleep(1); /* wait for child read message */
char buf[128]; /* buffer to receive data from child */
read(pipefd[READ],buf, sizeof buf);
close(pipefd[READ]);
close(pipefd[WRITE]);
printf("Returned from child %s",buf );
return 0;
} else { /* child */
char *s="send from child: ";
char buf[128];
read(pipefd[READ],buf, sizeof buf);
write(pipefd[WRITE],s,strlen(s));
close(pipefd[READ]);
close(pipefd[WRITE]);
return 0;
}
}

Resources