I would like to understand how message queues in Unix work. I wrote a simple code which sends a short message to queue and then I can read that message. But my code shows :
And I dont know why - and I cant see a message I send to queue. Heres my code:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
struct mymsgbuf {
long mtype;
char mtext[1024];
}msg;
int send_message(int qid, struct mymsgbuf *buffer )
{
int result = -1, length = 0;
length = sizeof(struct mymsgbuf) - sizeof(long);
if((result = msgsnd(qid, buffer, length, 0)) == -1)
return -1;
return result;
}
int read_message(int qid, long type, struct mymsgbuf *buffer)
{
int result, length;
length = sizeof(struct mymsgbuf) - sizeof(long);
if((result = msgrcv(qid, buffer, length, type, 0)) == -1)
return -1;
printf("Type: %ld Text: %s\n", buffer->mtype, buffer->mtext);
return result;
}
int main(int argc, char **argv)
{
int buffsize = 1024;
int qid = msgget(ftok(".", 0), IPC_CREAT | O_EXCL);
if (qid == -1)
{
perror("msgget");
exit(1);
}
msg.mtype = 1;
strcpy(msg.mtext, "my simple msg");
if((send_message(qid, &msg)) == -1)
{
perror("msgsnd");
exit(1);
}
if((read_message(qid, 1, &msg) == -1))
{
perror("msgrcv");
exit(1);
}
return 0;
}
When I changed a line with msgget for this line:
int qid = msgget(ftok(".", 0), IPC_CREAT | O_EXCL | 0600);
it shows:
From the documentation for msgget:
The low-order 9 bits of msg_perm.mode shall be set equal to the low-order 9 bits of msgflg.
You need to add some permissions to your queue, at least read and write. Do something like:
int qid = msgget(ftok(".", 0), IPC_CREAT | O_EXCL | 0600);
Related
I was working on a C programming database tutorial (linked here- https://www.youtube.com/watch?v=SEenaPQXxFs )
When I go to run my code and insert new data into the database it does generate a data file, but no data is stored in the data file/database at all- im not really sure why its not working, and as far as I can tell no errors populate.
The code I was working on is as follows
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
//give structure to record
typedef struct
{
unsigned int key; //primary key assingment
char fname[16]; // defines length allowed for names
char lname[16]; //same but for last name
unsigned int age;
} person_rec; //gives name to definition
int open_record(char *filename) //function to open record
{
int fd;
fd = open(filename, O_CREAT | O_APPEND, 0644);
if(fd == -1)
perror("open_record");
return fd;
}
void close_record(int fd) //close record
{
close(fd);
}
int insert_record(int fd, person_rec *rec) //unkkown
{
int ret;
ret = write(fd, rec, sizeof(person_rec));
return ret;
}
//function to delete and print
int get_record(int fd, person_rec *rec, int key)
{
int ret;
while( ( ret = read(fd, rec, sizeof(person_rec)) ) != -1)
{
if(ret == 0)
{
memset(rec, 0, sizeof(person_rec)); //clear any errors by resetting size
break;
return ret;
}
else if (key == rec->key)
return ret;
}
memset(rec, 0, sizeof(person_rec)); //clear record if error due to -1 size
return ret;
}
//delete function
int delete_record(int fd, int key)
{
int ret;
person_rec rec;
off_t pos;
pos = lseek(fd, 0, SEEK_SET);
while( ( ret = read(fd, &rec, sizeof(person_rec)) ) != -1)
{
if(ret == 0)
{
return ret;
}
else if (key == rec.key)
{
lseek(fd, pos, SEEK_SET);
rec.key = 0;
ret = write(fd, &rec, sizeof(person_rec));
return ret;
}
pos = lseek(fd, 0, SEEK_CUR);
}
return ret;
}
int main(int argc, char *argv[]) //main function/uses all prior defined function to make database ect
{
int fd;
person_rec rec;
fd = open_record("data1");
if(argc > 1)
{
/* insert */
if(argc > 5 && !strcmp(argv[1], "insert"))
{
rec.key = atoi(argv[2]);
strcpy(rec.fname, argv[3]);
strcpy(rec.lname, argv[4]);
rec.age = atoi(argv[5]);
insert_record(fd, &rec);
}
/* delete */
if(argc > 2 && !strcmp(argv[1], "delete"))
delete_record(fd, atoi(argv[2]));
/*print */
if(argc > 2 && !strcmp(argv[1], "print"))
{
get_record(fd, &rec, atoi(argv[2]));
printf("key = %d\n", rec.key);
printf("First = %s\n", rec.fname);
printf("Last = %s\n", rec.lname);
printf("Age = %d\n", rec.age);
}
}
return 0;
}
From the open man page:
The argument flags must include one of the following access modes: O_RDONLY, O_WRONLY, or O_RDWR.
So:
fd = open(filename, O_CREAT | O_APPEND, 0644);
should be:
fd = open(filename, O_CREAT | O_APPEND | O_RDWR, 0644);
I don't see any call to fclose() or fflush() to empty buffer to disk. Add fflush() after every write or fclose() before exiting the program.
This question already has answers here:
When using regex in C, \d does not work but [0-9] does
(4 answers)
Closed 3 years ago.
In the following code, I am trying to filter out using regex ONLY, the file called test.jpg, what am I doing wrong as the code below is not filtering this out?
I know there are simpler ways, but eventually I would like to change the regex to ^(image_)\\d{3,6}_201412\\d{2}_\\d{6}\\.(jpg)
and also my folder contains 100,000+ files, so I can only use the c getdents function which is super fast compared to any other way
I get the following output:
**************found*******
image_0179_20141212_060714.jpg
#define _GNU_SOURCE
#include <dirent.h> /* Defines DT_* constants */
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <string.h>
#include <regex.h>
#include <stdio.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
struct linux_dirent {
long d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[];
};
#define BUF_SIZE 1024*1024*5
int
main(int argc, char *argv[])
{
int fd, nread;
char buf[BUF_SIZE];
struct linux_dirent *d;
int bpos;
char d_type;
regex_t reg;
regmatch_t pmatch[40];
#define NAME "image_0179_20141212_060714.jpg"
const char *pattern = "^(image_)\\d{3,6}_201412\\d{2}_\\d{6}\\.(jpg)";
regcomp(®, pattern, REG_ICASE | REG_EXTENDED);
int retval = 0;
char buffer[1024] = "";
fd = open(argc > 1 ? argv[1] : ".", O_RDONLY | O_DIRECTORY);
if (fd == -1)
handle_error("open");
for ( ; ; )
{
nread = syscall(SYS_getdents, fd, buf, BUF_SIZE);
if (nread == -1)
handle_error("getdents");
if (nread == 0)
break;
for (bpos = 0; bpos < nread;)
{
d = (struct linux_dirent *) (buf + bpos);
d_type = *(buf + bpos + d->d_reclen - 1);
if( d->d_ino != 0 && d_type == DT_REG )
{
//printf("%s\n", (char *)d->d_name );
if (strstr(d->d_name, NAME) != NULL)
{
printf("**************found*******\n");
printf("%s\n", (char *)d->d_name );
};
retval = regexec(®, d->d_name, 2, pmatch, 0);
//printf("%d\n",retval);
if(retval==0)
{
printf("**************found regex*******\n");
printf("%s\n", (char *)d->d_name );
}
}
bpos += d->d_reclen;
}
}
regfree(®);
exit(EXIT_SUCCESS);
}
use the following regex instead
^image_[0-9]{3,6}_201412[0-9]{2}_[0-9]{6}\.jpg$
I've been working on a project and one of the tasks that I have to do is passing the string received from another process through a pipe to yet another process but this time I have to use a message queue.
I've managed to learn how msgqueue works and made a simple working program but, the thing is, it works when receiving a string from stdin through fgets.
My question is:
Can I pass a string that is already saved in other variable (for example
char s[20] = "message test"; ) to the msgqueues mtext?
My simple program looks like that:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>
struct msgbuf {
long mtype;
char string[20];
};
struct msgbuf mbuf;
int open_queue( key_t keyval ) {
int qid;
if((qid = msgget( keyval, IPC_CREAT | 0660 )) == -1)
return(-1);
return(qid);
}
int send_message( int qid){
int result, size;
size = sizeof mbuf.string;
if((result = msgsnd( qid, &mbuf, size, 0)) == -1)
return(-1);
return(result);
}
int remove_queue( int qid ){
if( msgctl( qid, IPC_RMID, 0) == -1)
return(-1);
return(0);
}
int read_message( int qid, long type){
int result, size;
size = sizeof mbuf.string;
if((result = msgrcv( qid, &mbuf, size, type, 0)) == -1)
return(-1);
return(result);
}
int main(void){
int qid;
key_t msgkey;
msgkey = ftok(".", 'm');
if(( qid = open_queue( msgkey)) == -1) {
perror("openErr");
exit(1);
}
mbuf.mtype = 1;
fgets(mbuf.string, sizeof mbuf.string, stdin);
if((send_message( qid)) == -1) {
perror("sendErr");
exit(1);
}
mbuf.mtype = 1;
if((read_message(qid, mbuf.mtype))== -1){
perror("recERR");
exit(1);
}
printf("Queue: %s\n", mbuf.string);
remove_queue(qid);
return 0;
}
Your code uses fgets() to fill the buffer mbuf.string with input read from stdin. You can instead use something like strcpy(mbuf.string, "message test") where you can pass in a variable or use a hard coded string.
I recommend using the POSIX message queue API as the System V API is deprecated.
i want to know if a queue message is empty or not . i have used msg_ctl() as follows it doesn't work :
struct msqid_ds buf;
int num_messages;
rc = msgctl(msqid, IPC_STAT, &buf);
and i've used this peek function :
int peek_message( int qid, long type )
{
int result, length;
if((result = msgrcv( qid, NULL, 0, type, IPC_NOWAIT)) == -1) {
if(errno==E2BIG)
return(1);
}
return(0);
}
in both cases i get the same result before and after sending a message to the queue.
the message gets to the queue successfully , i've tested that with reading what i've sent.
I wrote the sample code that does seem to work properly:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <errno.h>
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
int main(void) {
int msqid;
//msqid = msgget(IPC_PRIVATE, (IPC_CREAT | IPC_EXCL | 0600));
msqid = msgget((key_t)1235, 0600 | IPC_CREAT);
printf("Using message queue %d\n", msqid);
struct msqid_ds buf;
int rc = msgctl(msqid, IPC_STAT, &buf);
uint msg = (uint)(buf.msg_qnum);
printf("# messages before post: %u\n", msg);
printf("Posting message to queue...\n");
struct msgbuf qmsg;
qmsg.mtype = 100;
qmsg.mtext[0] = 'T';
int res = msgsnd(msqid, &qmsg, 1, MSG_NOERROR);
rc = msgctl(msqid, IPC_STAT, &buf);
msg = (uint)(buf.msg_qnum);
printf("# messages after post: %u\n", msg);
return 0;
}
Maybe that will be helpful to you? The number of messages on the queue does seem to increment correctly when using this code.
Why does the following code print ‘read(): Resource temporarily unavailable’ 80% of the time? That is the EAGAIN code, which is the same as WOULD BLOCK which means there is no data waiting to be read, but select is returning 1 saying there is data (tested in Linux):
#include <time.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/errno.h>
int main(int argc, char** argv)
{
int fd = open("/dev/lp0", O_RDWR | O_NONBLOCK);
int ret = 0;
int status = 0;
char buffer[1024];
char teststr[] = "This is a test\n";
char XMIT_STATUS_OFFLINE[] = {0x10,0x04,0x02};
char XMIT_STATUS_ERROR[] = {0x10,0x04,0x03};
char XMIT_STATUS_ROLL[] = {0x10,0x04,0x04};
char XMIT_STATUS_SLIP[] = {0x10,0x04,0x05};
fd_set rfds;
FD_ZERO( &rfds );
FD_SET( fd, &rfds );
struct timeval sleep;
sleep.tv_sec = 5;
sleep.tv_usec = 0;
/* Offline status */
ret = write(fd, XMIT_STATUS_OFFLINE, sizeof(XMIT_STATUS_OFFLINE));
//printf("write() returned %d\n", ret);
do {
ret = select( fd + 1, &rfds, NULL, NULL, &sleep );
} while (ret < 0 && (errno == EINTR));
ret = read(fd, buffer, 1024);
if(ret == -1) {
perror("read(): ");
} else {
status = buffer[0];
if((status & 0x04) != 0)
{
printf("The cover is open.\n");
} else {
printf("OFFLINE is good.\n");
}
}
close(fd);
return 0;
}
Your select call will return 0 after the 5 second timeout elapses if no data is available. Your code will ignore this and try to read from the device anyways. Check for ret == 0 and that will fix your problem.