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