The main purpose here is to create a message queue by executing thise command : ./create_msg_queue fileForQueue
We want to create the file fileForQueue if it doesn't exist.
Regarding my code, if the file doesn't exist, I get this error
ftok: No such file or directory
So how can I have this file create BEFORE ftok() is called with the file name ?
Provided code :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
// IPC and KEYS -------------
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/wait.h>
//---------------------------
#define _XOPEN_SOURCE
// message structure
typedef struct {
// id message
long type;
// Size : 12 bytes
double mesure;
pid_t pidClient;
} message_t;
int main (int argc, char * argv []) {
key_t key;
message_t message;
int file;
int pid;
// Check arg number
if (argc != 2) {
fprintf(stderr, "Syntaxe : %s fichier_clé\n",argv[0]);
exit(EXIT_FAILURE);
}
// Create the empty file given in parameter
if ((pid = vfork()) == -1)
{
perror("fork");
exit(1);
}
if (pid)
{
// code replacement to create the FILE
execlp("touch", "touch", argv[1], NULL);
perror("execlp");
exit(1);
}else
{
// Trying to wait for the forked() process to finish its file creation
wait (NULL);
// I GET ERROR HERE IF THE FILE DON'T EXIST BEFORE I LAUNCH THE PROGRAM
// Create key with the file given in parameter and then created
if ((key = ftok(argv[1], 0)) == -1) {
// errNo value
perror("ftok");
exit(EXIT_FAILURE);
}
// Create message queue
if ((file = msgget(key, IPC_CREAT | 0666)) == -1) {
perror("msgget");
exit(EXIT_FAILURE);
}
// Registering message content
message.type = 1;
message.mesure = -1;
message.pidClient = getpid();
// Sending message
if (msgsnd(file, (void *) & message, 12, 0) <0) {
perror("msgsnd");
exit(EXIT_FAILURE);
}
}
return EXIT_SUCCESS;
}
Thanks in advance for help. I struggle :)
key_t ftok(const char *path, int id);
ftok(argv[1], 0))
Only the low-order 8-bits of id are significant. The behavior of
ftok() is unspecified if these bits are 0.
Also note that you have to
#define _XOPEN_SOURCE
at the very begin
Related
I have written a program in c that creates a child process for receiving messages and the parent sends messages. It will not receive messages from its parent process, this is by design and my reason for using MSG_EXCEPT. So it is intended to have 2 instances of the program running, and they can send and receive messages. The issue is that the program only sends some messages, not all, and I have no clue why...
Also, I have to use gcc -D_GNU_SOURCE chat.c -o chat to compile, otherwise it has an error about MSG_EXCEPT. Does anyone know a better way to get MSG_EXCEPT to work without using those compiler flags? Something in code would be preferable, so that this can be portable.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <time.h>
#include <signal.h>
#include <errno.h>
typedef struct messageBuffer {
long type;
char text[256];
} MsgBuf;
typedef struct MessageStruct {
MsgBuf message;
int success;
} Message;
void handler(int sig){
_exit(0);
}
int open_queue( key_t keyval )
{
int qid;
if((qid = msgget( keyval, IPC_CREAT | 0666 )) == -1)
{
return(-1);
}
return qid;
}
void SendMessage(int qid, int msgtype, char* msgtxt)
{
MsgBuf msg;
time_t t;
msg.type = msgtype;
snprintf(msg.text, sizeof(msg.text), "%s", msgtxt);
time(&t);
if(msgsnd(qid, (void*)&msg, sizeof(msg.text), IPC_NOWAIT) == -1)
{
perror("msgsnd error");
exit(EXIT_FAILURE);
}
}
Message ReceiveMessage(int qid, int msgtype)
{
Message msg;
msg.success = 1;
if(msgrcv(qid, (void*)&msg.message, sizeof(msg.message.text), msgtype, IPC_NOWAIT | MSG_NOERROR | MSG_EXCEPT) == -1)
{
if (errno != ENOMSG)
{
perror("msgrcv");
exit(EXIT_FAILURE);
}
else
msg.success = 0;
}
return msg;
}
void ClearCurrentConsoleLine()
{
printf("\x1b[1F"); // Move to beginning of previous line
printf("\x1b[2K"); // Clear entire line
}
int main(void)
{
pid_t pid;
pid_t ppid = getpid();
int msgkey = 6666;
char str[256];
Message msg;
char* writemsg = "Write your message below:\n";
pid = fork();
int qid = open_queue(msgkey);
if(qid == -1)
{
perror("msgget");
exit(EXIT_FAILURE);
}
if(pid < 0)
{
perror("Forking error!");
abort();
}
else if(pid == 0)
{
signal(SIGCONT,handler);
while(1)
{
msg = ReceiveMessage(qid, ppid);
if(msg.success)
{
ClearCurrentConsoleLine();
printf("message: %ld: %s\n", msg.message.type, msg.message.text);
printf("%s", writemsg);
}
}
exit(0);
}
while(1)
{
printf("%s", writemsg);
fgets(str, sizeof(str), stdin);
int n = strlen(str);
if(str[n-1] == '\n')
str[n-1] = '\0';
ClearCurrentConsoleLine();
ClearCurrentConsoleLine();
printf("Me: %s\n", str);
if(strcmp(str, "exit") == 0)
{
printf("exiting\n");
break;
}
SendMessage(qid, ppid, str);
}
printf("Killing: %d\n", pid);
kill(pid,SIGCONT);
exit(0);
}
MSG_EXCEPT should not be used here, just remove this flag
MSG_EXCEPT
Used with msgtyp greater than 0 to read the first message
in the queue with message type that differs from msgtyp.
Turns out there was just an issue with that specific message queue. So I just closed the message queue and started a new one and all fixed. In regards to the MSG_EXCEPT, I need to use that because I don't want to just get any message currently in the queue, as I would with 0, I want to get any message that is not submitted by myself, any message except one with the key that I am using to send them. Another way I could do this would be to have 2 message queues per process, one for acquiring the key and message queue of another chat process, and one for sending messages between that other chat process, but this would increase complexity and this is just meant to be a simple implementation.
I have main program which creates two children and one named pipe(FIFO). Each children executes a program called “sendSignal" via execv(). One of the argument of the “sendSignal” is the FIFO in the main program.
The children are going to send signal to each other. It decided with an argument in the main (in variable firstShooter)program which signal shoot first.
I want to know how these two children can send each other their pid through this named pipe.
Following is the main program:
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
/* this program should be provided with 2 arguments */
int main(int argc, char **argv)
{
char str1[15];
char str2[15];
char fileDescriptor[15];
char *my_args[4];
char *myfifo = "myfifo";
int fd, pipeCheck;
pid_t pid1, pid2, wid;
/* If the user does not provide the argument to determin which child is firing first */
if(argc != 2)
{
fprintf(stderr,"%s: 2 arguments needed, got %d\n",argv[0],argc-1);
exit(1);
}
/* create the FIFO (named pipe) */
pipeCheck = mkfifo(myfifo, 0666);
/* check if the named pipe was created properly if not output an error */
if(pipeCheck == -1)
{
fprintf(stderr, "%s: Error creating named pipe: %s\n",argv[0], strerror(errno));
exit(1);
}
pid1 = fork();
if (pid1 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid1 == 0)
{
my_args[0] = "sendSignal";
my_args[1] = argv[1];
my_args[2] = myfifo; // the named pipe as arguemnt
my_args[3] = NULL;
execv("sendSignal",my_args);
fprintf(stderr,"sendSignal cannot be executed by first child...");
exit(-1);
}
pid2 = fork();
if(pid2 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid2 == 0)
{
my_args[0] = "sendSignal";
my_args[1] = argv[1];
my_args[2] = myfifo; // named pipe as arguemnt
my_args[3] = NULL;
// printf("this is converted = %s\n",my_args[1]);
execv("sendSignal",my_args);
fprintf(stderr,"sendSignal cannot be executed by second child...");
exit(-1);
}
close(fd);
unlink(myfifo);
wid = wait(NULL);
return 0;
}
here is the sendSignal:
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
void sig_handler(int signo)
{
if(signo == SIGUSR1)
printf("signal received\n");
}
int main(int argc, char **argv)
{
char abspath[256] = "";
getcwd(abspath, 256);
strrchr(abspath, '/');
if(signal(SIGUSR1,sig_handler) == SIG_ERR)
printf("\n Cannot catch the signal\n");
char *myfifo = "myfifo";
int firstShooter = atoi(argv[1]); //define the first process to send the signal
int fd;
char str1[15];
char str2[15];
char pid1[15];
char pid2[15];
fd = open(argv[2],O_RDWR);
if(firstShooter == 1)
{
sprintf(pid1,"%d",getpid());
write(fd,pid1,sizeof(pid1));
}
if(firstShooter == 2)
{
sprintf(pid2,"%d",getpid());
write(fd,pid2,sizeof(pid2));
}
read(fd,str1,sizeof(str2));
read(fd,str2,sizeof(str2));
close(fd);
printf("str1 = %s\n",str1);
printf("str2 = %s\n",str2);
return 0;
}
Both of your children processes got the same arguments:
my_args[0] = "sendSignal";
my_args[1] = argv[1];
my_args[2] = myfifo; // the named pipe as argument
my_args[3] = NULL;
firstShooter parameter doesn't make sense as process cannot identify itself as first or second.
I suggest to add one more parameter - process index. sendSignal function logic can be modified this way:
char pid1[15];
char pid2[15];
int processIndex = atoi(argv[3]);
fd = open(argv[2],O_RDWR);
if (processIndex == firstShooter)
{
// Send firstShooter PID
sprintf(pid1,"%d",getpid());
write(fd,pid1,sizeof(pid1));
// Got the other PID
read(fd,pid2,sizeof(pid2));
}
else
{
// Got the firstShooter PID
read(fd,pid1,sizeof(pid1));
// Send the other PID
sprintf(pid2,"%d",getpid());
write(fd, pid2, sizeof(pid2));
}
close(fd);
printf("pid1 = %s\n",pid1);
printf("pid2 = %s\n",pid2);
There are some issues in the way you have implemented.
1.Calling two fork() in the main program will be creating more than two child processes.(3 child processes). So give a condition to check that you are calling the next fork in the context of the parent itself.
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
/* this program should be provided with 2 arguments */
int main(int argc, char **argv)
{
int * status;
char str1[15];
char str2[15];
char fileDescriptor[15];
char *my_args[4];
char *myfifo = "myfifo";
int fd, pipeCheck;
pid_t pid1, pid2, wid;
/* If the user does not provide the argument to determin which child is firing first */
if(argc != 2)
{
fprintf(stderr,"%s: 2 arguments needed, got %d\n",argv[0],argc-1);
exit(1);
}
/* create the FIFO (named pipe) */
pipeCheck = mkfifo(myfifo, 0666);
/* check if the named pipe was created properly if not output an error */
if(pipeCheck == -1)
{
fprintf(stderr, "%s: Error creating named pipe: %s\n",argv[0], strerror(errno));
exit(1);
}
pid1 = fork();
if (pid1 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid1 == 0)//child
{
// printf("pid1=0\n");
printf("i am child 1 %d\n",getpid());
my_args[0] = "sendSignal";
my_args[1]=malloc(6);
sprintf(my_args[1] , "%d", getpid());
//my_args[1]="1";
printf("p%s\n",my_args[1]);
my_args[2] = myfifo; // the named pipe as arguemnt
my_args[3] ="1";
execv("sendSignal",my_args);
fprintf(stderr,"sendSignal cannot be executed by first child...");
exit(-1);
}
else if(pid1>0)// parent
{
// printf("pid1 %d",pid1);
waitpid(pid1,&status,WIFEXITED(status));
pid2 = fork();
// printf("p:%d",pid2);
if(pid2 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid2 == 0)
{
printf("i am child 2 %d\n",getpid());
my_args[0] = "sendSignal";
my_args[1]=malloc(6);
sprintf(my_args[1] , "%d", getpid());
my_args[2] = myfifo; // named pipe as arguemnt
my_args[3] = "2";
// printf("this is converted = %s\n",my_args[1]);
execv("sendSignal",my_args);
fprintf(stderr,"sendSignal cannot be executed by second child...");
exit(-1);
}
printf("done\n");
}
close(fd);
wait(NULL);
fd=open("fifo1", O_RDONLY);
char * space=(char *)malloc(6);
read(fd,space,6);
printf("from fifo1 %s",space);
fd=open("fifo2", O_RDONLY);
//char * space=(char *)malloc(6);
read(fd,space,6);
printf("from fifo2 %s",space);
//unlink(myfifo);
wid = wait(NULL);
unlink(myfifo);
return 0;
}
2. The two child process are accessing the same pipe. Pipe is for one way communication with an end for reading and another for writing. So create two pipes each for a process. I would suggest better not to go for pipes.
I have a program I'm writing with a globally defined File variable that I'm trying to access by the parent after it forks a child. However, the child is the one that is writing to the file so when I try to read it as the parent I get a Error: No such file or directory. Only it's not thrown as an error, it's stored in the tmpFP file. I'm not sure how to get around this.
I've omitted some code for legibility, the references to sockets are from a custom library, assume that works. The relevant comments should be in all caps, they point to where I believe the problem arises.
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <unistd.h>
#include <stdarg.h>
#include "Socket.h"
#include "ToUpper.h" /* definitions shared by client and server */
#define LINE_SIZE 50
#define MAX_WORDS 10
#define MAX_LINE 1024
#define MAX_TMP 100
#define MAX_ARGS 4 /* allows program name + 3 positional parameters */
#define MIN_ARGS 2 /* must have at least 1 positional parameter */
#define NUM_PARMS 4 /* allows program name + 2 parameters + NULL */
#define ERR_RETURN -1
/* variables to hold socket descriptors */
ServerSocket welcome_socket;
Socket connect_socket;
char new_line[MAX_LINE];
char tmp_name[MAX_TMP]; //DECLARING FILENAME
char id_str[MAX_TMP];
char arr[LINE_SIZE]={0};
int id;
FILE *fp; //FILE USED IN CHILD PROCESS
void toupper_service(void);
int main(int argc, char* argv[])
{
FILE *tmpFP; //FILE USED IN PARENT PROCESS
pid_t spid; /* pid_t is typedef for Linux process ID */
int c=0,index=0;
id = (int) getpid();
sprintf(id_str, "%d", id);
strcpy(tmp_name,"tmp");
strcat(tmp_name, id_str);
if (argc < 2)
{
printf("No port specified\n");
return (-1);
}
welcome_socket = ServerSocket_new(atoi(argv[1]));
connect_socket = ServerSocket_accept(welcome_socket);
Socket_close(welcome_socket);
while (c!=EOF)
{
while((c=Socket_getc(connect_socket))!='\n')
{
arr[index]=c;
index++;
}
arr[index]='\0';
/* accept an incoming client connection; blocks the
* process until a connection attempt by a client.
* creates a new data transfer socket.
*/
spid = fork(); /* create child == service process */
if (spid == -1)
{
perror("fork");
exit (-1);
}
if (spid == 0)
{/* code for the service process */
toupper_service();
Socket_close(connect_socket);
exit (0);
} /* end service process */
else /* daemon process closes its connect socket */
{
waitpid(spid,NULL,0);
//PASSES THIS TEST SOMEHOW
if((tmpFP = fopen (tmp_name, "r")) == NULL)
{
fprintf(stderr, "%s\n",tmp_name);
fprintf (stderr, "error opening tmp file\n");
exit (-1);
}
while((c=fgetc(tmpFP))!=EOF)
{
//PRINTS OUT ERROR HERE A LETTER AT A TIME
fprintf(stderr, "c: %d %c\n", c, (char)c);
Socket_putc(c, connect_socket);
}
remove(tmp_name);
Socket_putc('\0', connect_socket);
Socket_close(connect_socket);
/* reap a zombie every time through the loop, avoid blocking*/
}
}/* end of infinite loop for daemon process */
fprintf(stderr, "C: %d\n",c);
}
void toupper_service(void)
{
int i=0, c, pointer,num_words=0,index=0;
int too_many_words=0;
char *word[MAX_WORDS]={NULL};
//THIS IS THE OTHER PLACE TMP_NAME IS USED
fp = freopen(tmp_name, "w", stdout);
while ((c=arr[index])!='\0')
{
if(c==' '||c=='\t'||c=='\n') //word encountered
{
if(num_words>=MAX_WORDS-1)
{
printf("Too many commands passed\n");
too_many_words=1;
exit(0);
break;
}
arr[index]='\0';
word[num_words]=&arr[pointer];
pointer=i+1;
num_words++;
}
index++;
}
word[num_words]=NULL;
if(too_many_words==0)
{
c=0;
int error=execvp(word[0],word);
}
return;
}
I am trying to make this work but no luck, basically i need to write to the pipe and then make the pipe return back with the text i sent. I have a server.c and client.c , so i make the server.c run..., open a new terminal and then run the client.. the problem is that the client doesnt do anything when i run it.. I am sure i am missing something.. like closing the pipe. i am not sure.. I would really appreciate some guidance
server.c
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#define PIPE1 "PIPE1"
#define PIPE5 "PIPE5"
#define MAX_BUF_SIZE 255
int main(int argc, char *argv[])
{
int rdfd1,rdfd2,rdfd3,rdfd4, wrfd1,wrfd2,wrfd3,wrfd4,ret_val, count, numread1,numread2,numread3,numread4;
char buf1[MAX_BUF_SIZE];
char buf2[MAX_BUF_SIZE];
char buf3[MAX_BUF_SIZE];
char buf4[MAX_BUF_SIZE];
/* Create the first named - pipe */
ret_val = mkfifo(PIPE1, 0666);
if ((ret_val == -1) && (errno != EEXIST)) {
perror("Error creating the named pipe");
return 1;
}
ret_val = mkfifo(PIPE5, 0666);
if ((ret_val == -1) && (errno != EEXIST)) {
perror("Error creating the named pipe");
return 1;
}
/* Open the first named pipe for reading */
rdfd1 = open(PIPE1, O_RDONLY);
/* Open the first named pipe for writing */
wrfd1 = open(PIPE5, O_WRONLY);
/* Read from the pipes */
numread1 = read(rdfd1, buf1, MAX_BUF_SIZE);
buf1[numread1] = '0';
printf("Server : Read From the pipe : %sn", buf1);
/*
* Write the converted content to
* pipe
*/
write(wrfd1, buf1, strlen(buf1));
}
client.c
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PIPE1 "PIPE1"
#define PIPE5 "PIPE5"
#define MAX_BUF_SIZE 255
int main(int argc, char *argv[ ]) {
pid_t childpid;
int error;
int i;
int nprocs;
/* check command line for a valid number of processes to generate */
int wrfd1, rdfd1, numread;
char rdbuf[MAX_BUF_SIZE];
if ( (argc != 2) || ((nprocs = atoi (argv[1])) <= 0) ) {
fprintf (stderr, "Usage: %s nprocs\n", argv[0]);
return 1;
}
for (i = 1; i < nprocs; i++) {
/* create the remaining processes */
if ((childpid = fork()) == -1) {
fprintf(stderr, "[%ld]:failed to create child %d: %s\n", (long)getpid(), i, strerror(errno));
return 1;
}
/* Open the first named pipe for writing */
wrfd1 = open(PIPE5, O_WRONLY);
/* Open the second named pipe for reading */
rdfd1 = open(PIPE1, O_RDONLY);
if (childpid)
break;
char string1[100];
if(sprintf(string1, "This is process %d with ID %ld and parent id %ld\n", i, (long)getpid(), (long)getppid())) {
write(wrfd1,string1, strlen(string1));
}
/* Read from the pipe */
numread = read(rdfd1, rdbuf, MAX_BUF_SIZE);
rdbuf[numread] = '0';
printf("Full Duplex Client : Read From the Pipe : %sn", rdbuf);
}
return 0;
}
It seems like both server and client read from PIPE1 and write to PIPE5. Shouldn't one of them write to PIPE1 so that the other can read it from the other end?
Also, if you're testing with ./client 1, your for (i = 1; i < nprocs; i++) loop will never execute.
One last thing, see this question. I'm not entirely sure it applies to your code, but it's worth keeping in mind.
Shouldn't this line be '\0' ?
buf1[numread1] = '0';
I have the following application which replicates an issue I'm having in a larger application with system v message queues. basically, the main function generates a key, then creates a message queue with msgget(). Then 3 forks are spawned, each with a different id. each of them runs msgrcv with a different posative number (so they are waiting for different messages).
Main then sleeps for a few seconds a sends a message to id = 3. However it isn't the third thread that wakes up but a different one instead. This code is completely isolated so you can try it out yourself. What's wrong with this code?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/wait.h>
struct dummy_struct {
long mtype;
char message[255];
};
int msg_queue_id;
void recv_thread(int id);
int main(int argc, char **argv)
{
int i;
key_t key;
struct dummy_struct dummy = { 3, "hello" };
//create a unique key
if (key = ftok("/mnt/mydocuments/code/sys_v_fork_test/main.c", 'a') == -1)
{
printf("ftok didn't work\n");
exit(1);
}
//create the unix sys 5 message queue
if ((msg_queue_id = msgget(key, 0644 | IPC_CREAT)) == -1)
{
printf("msgget failed\n");
exit(1);
}
else
printf("my message queue id: %i\n", msg_queue_id);
//fork off multiple recievers
for (i = 1; i < 4; i++) // <- NOTE: 1 -> 4
{
if (fork() == 0)
recv_thread(i);
}
printf("sleeping\n");
sleep(5);
//wait a little then send a message
printf("sending message\n");
if (msgsnd(msg_queue_id, &dummy, sizeof(struct dummy_struct), 0) == -1)
{
printf("msgsnd failed\n");
}
printf("main thread exiting");
_exit(0);
}
void recv_thread(int id)
{
struct dummy_struct dummy;
printf("recv_thread with id: %i\n", id);
if (msgrcv(msg_queue_id, &dummy, sizeof(struct dummy_struct), id, 0) == -1)
printf("error in msgrcv\n");
else
printf("thread %i got %s back\n", id, dummy.message);
}
If I wait for 2 that means messages whose struct contains a mtype set to exactly 2. 3 for 3 and so one. My point of reference was this guide: http://www.ecst.csuchico.edu/~beej/guide/ipc/mq.html. Can anyone help please? (you may need to modify the ftok line of code to point to a valid file on your own machine to test successfully). I'm running Fedora 10 on an EeePC 1000H
Ahh think i've fixed it. It's because I was using an int rather than a long for the first member set in the structure for the "mtype". passing in { 1l, "hello" } instead and changing the definition of i to long seems to have fixed it