Adding shared memory implementation
Bernhard Reutner-Fischer
rep.dot.nop at gmail.com
Fri Jan 23 15:23:31 UTC 2009
On Fri, Jan 23, 2009 at 03:39:33PM +0100, Mikael Lund Jepsen, ICCC wrote:
> Mikael Lund Jepsen, ICCC wrote:
>>
>> Joakim Tjernlund wrote:
>>>> + /* skip opening slash */
>>>> + if (*name == '/')
>>>> + ++name;
>>>>
>>>
>>> I think skipping all leading '/' is better:
>>> for (; *name == '/'; ++name);
>>>
>> I took the newlib code verbatim to keep the number of different
>> implementations down,
>> but if we are making changes I think we should adopt the glibc code in
>> this case:
>> /* Construct the filename. */
>> while (name[0] == '/')
>> ++name;
>> Thanks,
>> Mikael
>>> Jocke
>>>
> Hi all,
>
> I've changed the patch as suggested by Joakim, but taking the glibc
> variant instead as explained previously.
> Also, the line in docs/uClibc_vs_SuSv3.txt stating that these functions
> are not implemented should be changed as well I think.
> I have not included that in the patch as I was not quite sure that it
> was ok to simply delete the line.
>
> The test app is unchanged, but attached again for convenience.
>
> Any takers on adding these to cvs?
>
> Thanks,
> Mikael
>#include <errno.h>
>#include <fcntl.h>
>#include <string.h>
>#include <stdio.h>
>#include <stdlib.h>
>#include <unistd.h>
>#include <sys/types.h>
>#include <sys/mman.h>
>#include <sys/stat.h>
>#include <sys/wait.h>
>
>
>char Commonname[] = "MyTestMem";
>int TestData[11] = {0,1,2,3,4,5,6,7,8,9,10};
>
>int main(void) {
> int pfds[2];
> pid_t pid;
> int hCommon;
> int TestdataFails = 0;
> char *pTestData;
> unsigned int i;
> char buf[30];
> int rv;
>
> pipe(pfds);
>
> switch(pid = fork()) {
> case -1:
> perror("fork");
> exit(1); // parent exits
>
> case 0:
> // Child
>
> // wait for parent
> read(pfds[0], buf, 5);
>
whitespace damage above.
> hCommon = shm_open(Commonname, O_RDWR, DEFFILEMODE);
> if (hCommon == -1) {
> perror("CHILD - shm_open(existing):");
> exit(1);
> } else {
> pTestData = mmap(0, sizeof(TestData), PROT_READ + PROT_WRITE, MAP_SHARED, hCommon, 0);
> if (pTestData != MAP_FAILED) {
> for (i=0; i < sizeof(TestData); i++) {
> if (pTestData[i] != TestData[i]) {
> printf("%-40s: Offset %d, local %d, shm %d", "Compare memory error", i, TestData[i], pTestData[i]);
> TestdataFails++;
> }
> }
> if (TestdataFails == 0)
> printf("%-40s: %s\n", "Compare memory", "Success");
>
> munmap(pTestData, sizeof(TestData));
> }
> }
> exit(0);
>
> default:
> // Parent
> hCommon = shm_open(Commonname, O_RDWR+O_CREAT+O_EXCL, DEFFILEMODE );
> if (hCommon == -1) {
> perror("PARENT - shm_open(create):");
> } else {
> if ((ftruncate(hCommon, sizeof(TestData))) == -1)
> {
> printf("%-40s: %s", "ftruncate", strerror(errno));
> shm_unlink(Commonname);
> return 0;
> }
>
> pTestData = mmap(0, sizeof(TestData), PROT_READ + PROT_WRITE, MAP_SHARED, hCommon, 0);
> if (pTestData == MAP_FAILED)
> {
> perror("PARENT - mmap:");
> if (shm_unlink(Commonname) == -1) {
> perror("PARENT - shm_unklink:");
> }
> return 0;
> }
> for (i=0; i <sizeof(TestData); i++)
> pTestData[i] = TestData[i];
>
> // signal child
> write(pfds[1], "rdy", 5);
> // wait for child
> wait(&rv);
>
> // Cleanup
> munmap(pTestData, sizeof(TestData));
> if (shm_unlink(Commonname) == -1) {
> perror("PARENT - shm_unklink:");
> }
> }
> }
> return 0;
>}
This can simply be dropped into the proper tests/ subdir, no?
>diff --git a/librt/shm_open.c b/librt/shm_open.c
>new file mode 100644
>index 0000000..cb92c3a
>--- /dev/null
>+++ b/librt/shm_open.c
>@@ -0,0 +1,48 @@
>+/* shm_open - open a shared memory file */
>+
>+/* Copyright 2002, Red Hat Inc. */
>+
>+#include <sys/types.h>
>+#include <sys/mman.h>
>+#include <unistd.h>
>+#include <string.h>
>+#include <fcntl.h>
>+#include <limits.h>
>+
>+int
>+shm_open (const char *name, int oflag, mode_t mode)
>+{
>+ int fd;
>+ char shm_name[PATH_MAX+20] = "/dev/shm/";
That's a bit excessive, don't you think.
>+
>+ /* Construct the filename. */
>+ while (name[0] == '/')
>+ ++name;
>+
>+ /* create special shared memory file name and leave enough space to
>+ cause a path/name error if name is too long */
>+ strlcpy (shm_name + 9, name, PATH_MAX + 10);
sounds like a BSD extension.
>+
>+ fd = open (shm_name, oflag, mode);
>+
>+ if (fd != -1)
>+ {
>+ /* once open we must add FD_CLOEXEC flag to file descriptor */
>+ int flags = fcntl (fd, F_GETFD, 0);
>+
>+ if (flags >= 0)
>+ {
>+ flags |= FD_CLOEXEC;
>+ flags = fcntl (fd, F_SETFD, flags);
I would write this as
if (flags >= 0)
flags = fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
but that shouldn't make a difference.
please look at the size(1) output for those two files and fix them.
TIA,
Bernhard
>+ }
>+
>+ /* on failure, just close file and give up */
>+ if (flags == -1)
>+ {
>+ close (fd);
>+ fd = -1;
>+ }
>+ }
>+
>+ return fd;
>+}
>diff --git a/librt/shm_unlink.c b/librt/shm_unlink.c
>new file mode 100644
>index 0000000..cf259c6
>--- /dev/null
>+++ b/librt/shm_unlink.c
>@@ -0,0 +1,28 @@
>+/* shm_unlink - remove a shared memory file */
>+
>+/* Copyright 2002, Red Hat Inc. */
>+
>+#include <sys/types.h>
>+#include <sys/mman.h>
>+#include <unistd.h>
>+#include <string.h>
>+#include <limits.h>
>+
>+int
>+shm_unlink (const char *name)
>+{
>+ int rc;
>+ char shm_name[PATH_MAX+20] = "/dev/shm/";
>+
>+ /* Construct the filename. */
>+ while (name[0] == '/')
>+ ++name;
>+
>+ /* create special shared memory file name and leave enough space to
>+ cause a path/name error if name is too long */
>+ strlcpy (shm_name + 9, name, PATH_MAX + 10);
>+
>+ rc = unlink (shm_name);
>+
>+ return rc;
>+}
More information about the uClibc
mailing list