hope@gatech.CSNET (Theodore Hope) (02/12/86)
Since I'm the one who originally asked for info regarding the use of the message queue system calls, let me say a few things. First of all, thanks to all who responded. The man pages for msgop(2) describe the msgbuf struct as containing long mtype; /* message type */ char mtext []; /* message text */ This kind of struc, especially in a syscall-passing sense, seems odd to me. It is obvious that mtext should be char mtext [some_number]; "Oh," said I. "I'll bet that's a misprint. Let's look at the <sys/msg.h> file to see what they _really_ mean." Well, surprise. The .h file defines struct msgbuf { long mtype; char mtext [1]; <- Notice: it says [1] } Am I overlooking something obvious? After looking through the kernel source, it appeared that the msgsnd and msgrcv syscalls expect the data to start at msg.mtext, so by defining my own structs as struct Msgbuf { long mtype; char mtext [MAXMTEXT]; } everything is ok. Several folks suggested to read the Sys V IPC Primer, which I don't have handy. Others suggested the book "Advanced Systems Programming with Unix" (I can't remember the authors' names). -- Theodore Hope School of Information & Computer Science, Georgia Tech, Atlanta GA 30332 CSNet: hope@gatech ARPA: Hope%GATech.CSNet @ CSNet-Relay.ARPA uucp: ...!{akgua,allegra,amd,hplabs,ihnp4,seismo,ut-sally}!gatech!hope
friesen@psivax.UUCP (Stanley Friesen) (02/13/86)
In article <2666@gatech.CSNET> hope@gatech.CSNET (Theodore Hope) writes: > >This kind of struc, especially in a syscall-passing sense, seems odd to me. >It is obvious that mtext should be > > char mtext [some_number]; > >"Oh," said I. "I'll bet that's a misprint. Let's look at the <sys/msg.h> >file to see what they _really_ mean." Well, surprise. The .h file defines > > struct msgbuf { > long mtype; > char mtext [1]; <- Notice: it says [1] > } > >Am I overlooking something obvious? After looking through the kernel source, >it appeared that the msgsnd and msgrcv syscalls expect the data to start at >msg.mtext, > Well, it really isn't that obvious. The man page is *not* a misprint, and the .h file is "correct" also. What is happening here is a rather tricky piece of "C" coding to permit *variable* sized arrays to be passed without allocating all the space necessary for the maximum size, and without any real maximum size. Basically it is taking advantage of the fact that "C" doesn't check array subscripts and the way in which address calculation is done. Basically the declared array in the struct is only being used as the *base* of the array. Subscripting off that base will access succesively higher addresses, so that a unit "array" at the end of a struct can effectively be extended indefinately, merely by allocating space at the end of it. The way this is intended to be used is struct msgbuf *msgptr; msgptr = (struct msgbuf *)malloc(sizeof(struct msgbuf) + sizeof(message)); This way your msgbuf exactly matches the size of your message. Yeah, I know, a really obscure trick. I know about it because it is also used in the game Hack. -- Sarima (Stanley Friesen) UUCP: {ttidca|ihnp4|sdcrdcf|quad1|nrcvax|bellcore|logico}!psivax!friesen ARPA: ttidca!psivax!friesen@rand-unix.arpa
bet@ecsvax.UUCP (Bennett E. Todd III) (02/13/86)
In article <2666@gatech.CSNET> hope@gatech.CSNET (Theodore Hope) writes: > [...] >The man pages for msgop(2) describe the msgbuf struct as containing > > long mtype; /* message type */ > char mtext []; /* message text */ > > [...] The .h file defines > > struct msgbuf { > long mtype; > char mtext [1]; <- Notice: it says [1] > } > [...] You should follow net.lang.c; this has popped up there. What you are seeing is a C hack to permit variable-length structs. What you want to say is struct msgbuf { long mtype; /* message type */ char mtext []; /* variable length, NULL-terminated */ } but the C compiler croaks on that, so you use an array dimension of 1. Note that the only member of a struct that can get away with being varying length is the last member, and that only works because C doesn't do array bounds checking. So anyway, how do you use it? Like so. Say, perhaps, I am building messages in my own private array char textbuff[MAXMSGLEN]; then when I want to pass one in I roll up an empty struct msgbuf as follows: struct msgbuf *tmp_ptr; char *malloc(); ... tmp_ptr = (struct msgbuf *) malloc(sizeof(struct msgbuf) + strlen(textbuff)); if (tmp_ptr == NULL) perror(...); strcpy(tmp_ptr.mtext, textbuff); I kind of like the technique; it allows you to use as much space as needed and no more, without too much overhead or nuisance. Last I recall, the concensus was that the technique should be reasonably portable to any but the most rabidly pathological machine architectures. -Bennett -- Bennett Todd -- Duke Computation Center, Durham, NC 27706-7756; (919) 684-3695 UUCP: ...{decvax,seismo,philabs,ihnp4,akgua}!mcnc!ecsvax!duccpc!bet
bet@ecsvax.UUCP (Bennett E. Todd III) (02/13/86)
In article <2666@gatech.CSNET> hope@gatech.CSNET (Theodore Hope) writes: > [...] >The man pages for msgop(2) describe the msgbuf struct as containing > > long mtype; /* message type */ > char mtext []; /* message text */ > > [...] The .h file defines > > struct msgbuf { > long mtype; > char mtext [1]; <- Notice: it says [1] > } > [...] You should follow net.lang.c; this has popped up there. What you are seeing is a C hack to permit variable-length structs. What you want to say is struct msgbuf { long mtype; /* message type */ char mtext []; /* variable length, NULL-terminated */ } but the C compiler croaks on that, so you use an array dimension of 1. Note that the only member of a struct that can get away with being varying length is the last member, and that only works because C doesn't do array bounds checking. So anyway, how do you use it? Like so. Say, perhaps, I am building messages in my own private array char textbuff[MAXMTEXT]; then when I want to pass one in I roll up an empty struct msgbuf as follows: struct msgbuf *tmp_ptr; char *malloc(); ... tmp_ptr = (struct msgbuf *) malloc(sizeof(struct msgbuf) + strlen(textbuff)); if (tmp_ptr == NULL) perror(...); strcpy(tmp_ptr.mtext, textbuff); I kind of like the technique; it allows you to use as much space as needed and no more, without too much overhead or nuisance. Last I recall, the consensus was that the technique should be reasonably portable to any but the most rabidly pathological machine architectures. -Bennett -- Bennett Todd -- Duke Computation Center, Durham, NC 27706-7756; (919) 684-3695 UUCP: ...{decvax,seismo,philabs,ihnp4,akgua}!mcnc!ecsvax!duccpc!bet
gwyn@brl-smoke.ARPA (Doug Gwyn ) (02/16/86)
In article <2666@gatech.CSNET> hope@gatech.CSNET (Theodore Hope) writes: > >The man pages for msgop(2) describe the msgbuf struct as containing > > long mtype; /* message type */ > char mtext []; /* message text */ > >This kind of struc, especially in a syscall-passing sense, seems odd to me. >It is obvious that mtext should be > > char mtext [some_number]; > >"Oh," said I. "I'll bet that's a misprint. Let's look at the <sys/msg.h> >file to see what they _really_ mean." Well, surprise. The .h file defines > > struct msgbuf { > long mtype; > char mtext [1]; <- Notice: it says [1] > } > >Am I overlooking something obvious? After looking through the kernel source, >it appeared that the msgsnd and msgrcv syscalls expect the data to start at >msg.mtext, so by defining my own structs as > > struct Msgbuf { > long mtype; > char mtext [MAXMTEXT]; > } > >everything is ok. You got it right. The C language provides no way to declare a variable-length array in a struct, so the prototype in the documentation and the declaration in the header file represent the array as best they can. From a design standpoint it would have been preferable for the struct to have contained a pointer to the message buffer rather than the buffer itself, but that's not the way they designed it.