Discussion:
shared memory using mmap question
(too old to reply)
G G
2020-08-03 06:42:49 UTC
Permalink
the two following programs come from "Operating Systems
10th edition". pp 133,134

i first run the producer then the consumer,
i get a segmentation fault.

the ftruncate() has been commented out because of
a compiler warning,

producer_process.c:33:5: warning: implicit declaration
of function 'ftruncate' is invalid in C99
[-Wimplicit-function-declaration]
ftruncate( fd, SIZE );
^
1 warning generated.

Question: the programs should work?
in the producer, a file descriptor is created fd
it is named "OS"
the producer then uses mmap() to allocate shared memory,
and write into that location HelloWorld!

the consumer using the named fd, "OS", should read
from that shared location and should print
HelloWorld! to stand output the screen, right?

i am getting a segmentation fault. does that mean
i am trying to access a location in memory which
i don't have the privilege to do so?

Or is there a typo? :-)

/***************** producer process ******************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>

#include <sys/mman.h>


int main()
{
/* the size (in bytes) of shared memory object */
const int SIZE = 4096;

/* name of the shared memory object */
const char *name = "OS";

/* strings written to shared memory */
const char *message_0 = "Hello";
const char *message_1 = "World!";

/* shared memory file descriptor */
int fd;

/* pointer to shard memory object */
char *ptr;

/* create the shared memory object */
fd = shm_open( name, O_CREAT | O_RDWR, 0666);

/* configure the size of the shard memory object */
// ftruncate( fd, SIZE );

/* memory map the shared memory object */

ptr = (char *) mmap( 0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );

/* write to shared memory object */
sprintf( ptr, "%s", message_0 );
ptr += strlen( message_0 );
sprintf( ptr, "%s", message_1 );
ptr += strlen( message_1 );

return 0;

}


/*********************** consumer process ********************/

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>

#include <sys/mman.h>

int main()
{
/* the size (in bytes) of shared memory object */
const int SIZE = 4096;

/* name of the shared memory object */
const char *name = "OS";

/* shared memory file descriptor */
int fd;

/* pointer to shared memory object */
char *ptr;

/* open the shared memory object */
fd = shm_open( name, O_RDONLY, 0666);

/* memory map the shared memory object */
ptr = ( char * ) mmap( 0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );

/* read from the shared memory object */
printf( "%s", (char *) ptr );

/* remove the shared memory object */
shm_unlink( name );

return 0;

}
Keith Thompson
2020-08-03 07:44:34 UTC
Permalink
Post by G G
the two following programs come from "Operating Systems
10th edition". pp 133,134
i first run the producer then the consumer,
i get a segmentation fault.
the ftruncate() has been commented out because of
a compiler warning,
producer_process.c:33:5: warning: implicit declaration
of function 'ftruncate' is invalid in C99
[-Wimplicit-function-declaration]
ftruncate( fd, SIZE );
^
1 warning generated.
ftruncate is declared in <unistd.h>, which you didn't include.

The man page on my system says:

#include <unistd.h>
#include <sys/types.h>

The latter is for off_t.

[...]
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */
G G
2020-08-03 09:05:12 UTC
Permalink
Post by Keith Thompson
Post by G G
the two following programs come from "Operating Systems
10th edition". pp 133,134
i first run the producer then the consumer,
i get a segmentation fault.
the ftruncate() has been commented out because of
a compiler warning,
producer_process.c:33:5: warning: implicit declaration
of function 'ftruncate' is invalid in C99
[-Wimplicit-function-declaration]
ftruncate( fd, SIZE );
^
1 warning generated.
ftruncate is declared in <unistd.h>, which you didn't include.
#include <unistd.h>
#include <sys/types.h>
The latter is for off_t.
ah, thanks for the includes, but i still get a
zsh: segmentation fault ./consumer_process

the included libraries allow the ftruncate(...) to
compile without warning.

i'm using mac os 10.15.5,
Apple clang version 11.0.3 (clang-1103.0.32.62)
Target: x86_64-apple-darwin19.5.0
Thread model: posix
Peter van Hooft
2020-08-03 09:26:46 UTC
Permalink
Post by G G
Post by Keith Thompson
Post by G G
the two following programs come from "Operating Systems
10th edition". pp 133,134
i first run the producer then the consumer,
i get a segmentation fault.
the ftruncate() has been commented out because of
a compiler warning,
producer_process.c:33:5: warning: implicit declaration
of function 'ftruncate' is invalid in C99
[-Wimplicit-function-declaration]
ftruncate( fd, SIZE );
^
1 warning generated.
ftruncate is declared in <unistd.h>, which you didn't include.
#include <unistd.h>
#include <sys/types.h>
The latter is for off_t.
ah, thanks for the includes, but i still get a
zsh: segmentation fault ./consumer_process
the included libraries allow the ftruncate(...) to
compile without warning.
i'm using mac os 10.15.5,
Apple clang version 11.0.3 (clang-1103.0.32.62)
Target: x86_64-apple-darwin19.5.0
Thread model: posix
The issue is that in the consumer mmap fails with permission denied. The
options for shm_open conflict with those for mmap.
Use O_RDWR in shm_open.

It's always a good idea to check for error returns of functions you
call, even in example programs. In this case, mmap returns MAP_FAILED,
with errno set to `permission denied'.

peter
G G
2020-08-03 09:55:52 UTC
Permalink
Post by Peter van Hooft
Post by G G
Post by Keith Thompson
Post by G G
the two following programs come from "Operating Systems
10th edition". pp 133,134
i first run the producer then the consumer,
i get a segmentation fault.
the ftruncate() has been commented out because of
a compiler warning,
producer_process.c:33:5: warning: implicit declaration
of function 'ftruncate' is invalid in C99
[-Wimplicit-function-declaration]
ftruncate( fd, SIZE );
^
1 warning generated.
ftruncate is declared in <unistd.h>, which you didn't include.
#include <unistd.h>
#include <sys/types.h>
The latter is for off_t.
ah, thanks for the includes, but i still get a
zsh: segmentation fault ./consumer_process
the included libraries allow the ftruncate(...) to
compile without warning.
i'm using mac os 10.15.5,
Apple clang version 11.0.3 (clang-1103.0.32.62)
Target: x86_64-apple-darwin19.5.0
Thread model: posix
The issue is that in the consumer mmap fails with permission denied. The
options for shm_open conflict with those for mmap.
Use O_RDWR in shm_open.
It's always a good idea to check for error returns of functions you
call, even in example programs. In this case, mmap returns MAP_FAILED,
with errno set to `permission denied'.
peter
Ok, thanks peter. that works.
uh, how did you know that O_RDWR would work. The program uses read only.
hmm, why would it be necessary to have read and write access on the
consumer side? i mean once you found the error, by checking the returns,
was it a man page that told you that read/write access was necessary
for the shm_open().

thanks again.
Peter van Hooft
2020-08-03 10:32:20 UTC
Permalink
Post by G G
Post by Peter van Hooft
Post by G G
Post by Keith Thompson
Post by G G
the two following programs come from "Operating Systems
10th edition". pp 133,134
i first run the producer then the consumer,
i get a segmentation fault.
the ftruncate() has been commented out because of
a compiler warning,
producer_process.c:33:5: warning: implicit declaration
of function 'ftruncate' is invalid in C99
[-Wimplicit-function-declaration]
ftruncate( fd, SIZE );
^
1 warning generated.
ftruncate is declared in <unistd.h>, which you didn't include.
#include <unistd.h>
#include <sys/types.h>
The latter is for off_t.
ah, thanks for the includes, but i still get a
zsh: segmentation fault ./consumer_process
the included libraries allow the ftruncate(...) to
compile without warning.
i'm using mac os 10.15.5,
Apple clang version 11.0.3 (clang-1103.0.32.62)
Target: x86_64-apple-darwin19.5.0
Thread model: posix
The issue is that in the consumer mmap fails with permission denied. The
options for shm_open conflict with those for mmap.
Use O_RDWR in shm_open.
It's always a good idea to check for error returns of functions you
call, even in example programs. In this case, mmap returns MAP_FAILED,
with errno set to `permission denied'.
peter
Ok, thanks peter. that works.
uh, how did you know that O_RDWR would work. The program uses read only.
hmm, why would it be necessary to have read and write access on the
consumer side? i mean once you found the error, by checking the returns,
was it a man page that told you that read/write access was necessary
for the shm_open().
thanks again.
No, you get a permission denied. It kind of stands out that you want to
mmap the shm with read/write while shm_open-ing it with O_RDONLY.

peter
Rainer Weikusat
2020-08-03 12:08:33 UTC
Permalink
G G <***@gmail.com> writes:

[...]
Post by G G
Ok, thanks peter. that works.
uh, how did you know that O_RDWR would work. The program uses read only.
It doesn't.

/* open the shared memory object */
fd = shm_open( name, O_RDONLY, 0666);

/* memory map the shared memory object */
ptr = ( char * ) mmap( 0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );

Computers are even worse than humans at "guess what my hand-waiving was
supposed to mean": If you mmap something read/write, the kernel will
simply create a writeable mapping. Or not, if the access mode of the
underlying file prohibits that.
Jorgen Grahn
2020-08-03 13:13:01 UTC
Permalink
...
Post by Peter van Hooft
Post by G G
i'm using mac os 10.15.5,
Apple clang version 11.0.3 (clang-1103.0.32.62)
Target: x86_64-apple-darwin19.5.0
Thread model: posix
The issue is that in the consumer mmap fails with permission denied. The
options for shm_open conflict with those for mmap.
Use O_RDWR in shm_open.
It's always a good idea to check for error returns of functions you
call, even in example programs. In this case, mmap returns MAP_FAILED,
with errno set to `permission denied'.
And when you realize that you need error checking, before implementing
it you can run again under strace(1) or a non-Linux equivalent. It
gives you a good log of all system calls, with errno.

/Jorgen
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Kaz Kylheku
2020-08-03 21:05:54 UTC
Permalink
Post by G G
/* open the shared memory object */
fd = shm_open( name, O_RDONLY, 0666);
Where is the test for the success of this operation?

Also, as a mattery of style, consider avoiding assignments, wherever
possible, in favor of initializations:

int fd = shm_open(...)
char *ptr = (char *) mmap ...
Post by G G
/* memory map the shared memory object */
ptr = ( char * ) mmap( 0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
Why are you mapping something opened O_RDONLY with PROT_WRITE
protection?
Keith Thompson
2020-08-03 21:12:10 UTC
Permalink
Post by Kaz Kylheku
Post by G G
/* open the shared memory object */
fd = shm_open( name, O_RDONLY, 0666);
Where is the test for the success of this operation?
Also, as a mattery of style, consider avoiding assignments, wherever
int fd = shm_open(...)
char *ptr = (char *) mmap ...
And if this is C and not C++, the cast is unnecessary.
Post by Kaz Kylheku
Post by G G
/* memory map the shared memory object */
ptr = ( char * ) mmap( 0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
Why are you mapping something opened O_RDONLY with PROT_WRITE
protection?
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */
Rainer Weikusat
2020-08-03 22:00:37 UTC
Permalink
Post by Kaz Kylheku
Post by G G
/* open the shared memory object */
fd = shm_open( name, O_RDONLY, 0666);
Where is the test for the success of this operation?
Also, as a mattery of style, consider avoiding assignments, wherever
int fd = shm_open(...)
char *ptr = (char *) mmap ...
As a matter of style, I argue for the opposite: Don't declare a new
variable whenever you happen to believe you need one. Code which declares
a variable named i fifteen times because nobody could be arsed to check
if a variable i was already declared contains a lot of redundant text
and texts with lots of (pointless) repetitions are difficult to read and
understand.

Should a "variable declaration block" at the start of a function start
to become lengthy, that's a tell-tale sign that the functions is
"lengthy", too, specifically, "much too lengthy" [*]

[*] No, I don't believe that this concept of 1979 called functional
decomposition will ever gain traction. Real-world programmers like messy
code as much as messy desks :->. It's nevertheless still highly useful.
Kaz Kylheku
2020-08-04 18:47:10 UTC
Permalink
Post by Rainer Weikusat
Post by Kaz Kylheku
Post by G G
/* open the shared memory object */
fd = shm_open( name, O_RDONLY, 0666);
Where is the test for the success of this operation?
Also, as a mattery of style, consider avoiding assignments, wherever
int fd = shm_open(...)
char *ptr = (char *) mmap ...
As a matter of style, I argue for the opposite: Don't declare a new
variable whenever you happen to believe you need one. Code which declares
If a variable is calculated once and consumed only in one place, and the
expression which calculates is short and understadable, it makes sense
to eliminate the variable and just use the expression in its place.

However, that is not advisable unless you're sure that there are no
important side effects being reordered.

int ch = getchar();
int res = foo(fun_with_effect(), ch);

Here we know that getchar is called first, then fun_with_effect.
Not so if we eliminate the variable:

int res = foo(fun_with_effect(), getchar());

Variables give intermediate results names, which can clarify things.
Post by Rainer Weikusat
a variable named i fifteen times because nobody could be arsed to check
if a variable i was already declared contains a lot of redundant text
and texts with lots of (pointless) repetitions are difficult to read and
understand.
Declaring a separate dummy variable i in a block of code like this

{ /* C89 */
int i;
for (i = 0; ....) {

}
}

is actually a good idea. It follows the idea of minimal scope. An
identifier is introduced just before it is needed, and its scope ends
at the soonest point where it is no longer needed.

We know that any mention of any i elsewhere outside of this block is
referring to some other i.

It also illustrates why mixed declarations and statements are such a
misfeature:

type x = blah();

statement(x);
statement;

type y = foo();

// X has no "next use" any more, yet is still in scope.

statement(y);

Nested scopes should always have and *end* that is as short as possible,
not only a start. Above it is clear that x and y are declared close
to where they are needed; but then they linger way past no longer being
needed. You want:

{
type x = blah();

statement(x);
statement;

// X has no "next use" any more; consequently we cut off
// the scope here.
}

{
type y = foo();
statement(y);
}

It is so helpful to the reader to know where *not* to look for
interactions with a variable.

Loading...