📄 shm.cc
字号:
/* shm.cc: Single unix specification IPC interface for Cygwin. Copyright 2002 Red Hat, Inc. Written by Conrad Scott <conrad.scott@dsl.pipex.com>. Based on code by Robert Collins <robert.collins@hotmail.com>.This file is part of Cygwin.This software is a copyrighted work licensed under the terms of theCygwin license. Please consult the file "CYGWIN_LICENSE" fordetails. */#include "winsup.h"#include <sys/types.h>#include <assert.h>#include <errno.h>#include <stdio.h>#include <unistd.h>#include "cygerrno.h"#include "safe_memory.h"#include "sigproc.h"#include "cygserver_ipc.h"#include "cygserver_shm.h"/*---------------------------------------------------------------------------* * class client_shmmgr * * A singleton class. *---------------------------------------------------------------------------*/#define shmmgr (client_shmmgr::instance ())class client_shmmgr{private: class segment_t { public: const int shmid; const void *const shmaddr; const int shmflg; HANDLE hFileMap; // Updated by fixup_shms_after_fork (). segment_t *next; segment_t (const int shmid, const void *const shmaddr, const int shmflg, const HANDLE hFileMap) : shmid (shmid), shmaddr (shmaddr), shmflg (shmflg), hFileMap (hFileMap), next (NULL) {} };public: static client_shmmgr & instance (); void *shmat (int shmid, const void *, int shmflg); int shmctl (int shmid, int cmd, struct shmid_ds *); int shmdt (const void *); int shmget (key_t, size_t, int shmflg); int fixup_shms_after_fork ();private: static NO_COPY client_shmmgr *_instance; CRITICAL_SECTION _segments_lock; static segment_t *_segments_head; // List of attached segs by shmaddr. static long _shmat_cnt; // No. of attached segs; for info. only. client_shmmgr (); ~client_shmmgr (); // Undefined (as this class is a singleton): client_shmmgr (const client_shmmgr &); client_shmmgr & operator= (const client_shmmgr &); segment_t *find (const void *, segment_t **previous = NULL); void *attach (int shmid, const void *, int shmflg, HANDLE & hFileMap); segment_t *new_segment (int shmid, const void *, int shmflg, HANDLE);};/* static */ NO_COPY client_shmmgr *client_shmmgr::_instance;/* The following two variables must be inherited by child processes * since they are used by fixup_shms_after_fork () to re-attach to the * parent's shm segments. *//* static */ client_shmmgr::segment_t *client_shmmgr::_segments_head;/* static */ long client_shmmgr::_shmat_cnt;/*---------------------------------------------------------------------------* * client_shmmgr::instance () *---------------------------------------------------------------------------*/client_shmmgr &client_shmmgr::instance (){ if (!_instance) _instance = safe_new0 (client_shmmgr); assert (_instance); return *_instance;}/*---------------------------------------------------------------------------* * client_shmmgr::shmat () *---------------------------------------------------------------------------*/void *client_shmmgr::shmat (const int shmid, const void *const shmaddr, const int shmflg){ syscall_printf ("shmat (shmid = %d, shmaddr = %p, shmflg = 0%o)", shmid, shmaddr, shmflg); EnterCriticalSection (&_segments_lock); HANDLE hFileMap = NULL; void *const ptr = attach (shmid, shmaddr, shmflg, hFileMap); if (ptr) new_segment (shmid, ptr, shmflg, hFileMap); LeaveCriticalSection (&_segments_lock); if (ptr) syscall_printf ("%p = shmat (shmid = %d, shmaddr = %p, shmflg = 0%o)", ptr, shmid, shmaddr, shmflg); // else // See the syscall_printf in client_shmmgr::attach (). return (ptr ? ptr : (void *) -1);}/*---------------------------------------------------------------------------* * client_shmmgr::shmctl () *---------------------------------------------------------------------------*/intclient_shmmgr::shmctl (const int shmid, const int cmd, struct shmid_ds *const buf){ syscall_printf ("shmctl (shmid = %d, cmd = 0x%x, buf = %p)", shmid, cmd, buf); // Check parameters and set up in parameters as required. const struct shmid_ds *in_buf = NULL; switch (cmd) { case IPC_SET: if (__check_invalid_read_ptr_errno (buf, sizeof (struct shmid_ds))) { syscall_printf (("-1 [EFAULT] = " "shmctl (shmid = %d, cmd = 0x%x, buf = %p)"), shmid, cmd, buf); set_errno (EFAULT); return -1; } in_buf = buf; break; case IPC_STAT: case SHM_STAT: if (__check_null_invalid_struct_errno (buf, sizeof (struct shmid_ds))) { syscall_printf (("-1 [EFAULT] = " "shmctl (shmid = %d, cmd = 0x%x, buf = %p)"), shmid, cmd, buf); set_errno (EFAULT); return -1; } break; case IPC_INFO: if (__check_null_invalid_struct_errno (buf, sizeof (struct shminfo))) { syscall_printf (("-1 [EFAULT] = " "shmctl (shmid = %d, cmd = 0x%x, buf = %p)"), shmid, cmd, buf); set_errno (EFAULT); return -1; } break; case SHM_INFO: if (__check_null_invalid_struct_errno (buf, sizeof (struct shm_info))) { syscall_printf (("-1 [EFAULT] = " "shmctl (shmid = %d, cmd = 0x%x, buf = %p)"), shmid, cmd, buf); set_errno (EFAULT); return -1; } break; } // Create and issue the command. client_request_shm request (shmid, cmd, in_buf); if (request.make_request () == -1 || request.error_code ()) { syscall_printf (("-1 [%d] = " "shmctl (shmid = %d, cmd = 0x%x, buf = %p)"), request.error_code (), shmid, cmd, buf); set_errno (request.error_code ()); return -1; } // Some commands require special processing for their out parameters. int result = 0; switch (cmd) { case IPC_STAT: *buf = request.ds (); break; case IPC_INFO: *(struct shminfo *) buf = request.shminfo (); break; case SHM_STAT: // ipcs(8) i'face. result = request.shmid (); *buf = request.ds (); break; case SHM_INFO: // ipcs(8) i'face. result = request.shmid (); *(struct shm_info *) buf = request.shm_info (); break; } syscall_printf ("%d = shmctl (shmid = %d, cmd = 0x%x, buf = %p)", result, shmid, cmd, buf); return result;}/*---------------------------------------------------------------------------* * client_shmmgr::shmdt () * * According to Posix, the only error condition for this system call * is EINVAL if shmaddr is not the address of the start of an attached * shared memory segment. Given that, all other errors just generate * tracing noise. *---------------------------------------------------------------------------*/intclient_shmmgr::shmdt (const void *const shmaddr){ syscall_printf ("shmdt (shmaddr = %p)", shmaddr); EnterCriticalSection (&_segments_lock); segment_t *previous = NULL; segment_t *const segptr = find (shmaddr, &previous); if (!segptr) { LeaveCriticalSection (&_segments_lock); syscall_printf ("-1 [EINVAL] = shmdt (shmaddr = %p)", shmaddr); set_errno (EINVAL); return -1; } assert (previous ? previous->next == segptr : _segments_head == segptr); if (previous) previous->next = segptr->next; else _segments_head = segptr->next; LeaveCriticalSection (&_segments_lock); const long cnt = InterlockedDecrement (&_shmat_cnt); assert (cnt >= 0); if (!UnmapViewOfFile ((void *) shmaddr)) syscall_printf (("failed to unmap view " "[shmid = %d, handle = %p, shmaddr = %p]:" "%E"), segptr->shmid, segptr->hFileMap, shmaddr); assert (segptr->hFileMap); if (!CloseHandle (segptr->hFileMap)) syscall_printf (("failed to close file map handle " "[shmid = %d, handle = %p]: %E"), segptr->shmid, segptr->hFileMap); client_request_shm request (segptr->shmid); if (request.make_request () == -1 || request.error_code ()) syscall_printf ("shmdt request failed [shmid = %d, handle = %p]: %s", segptr->shmid, segptr->hFileMap, strerror (request.error_code ())); safe_delete (segptr); syscall_printf ("0 = shmdt (shmaddr = %p)", shmaddr); return 0;}/*---------------------------------------------------------------------------* * client_shmmgr::shmget () *---------------------------------------------------------------------------*/intclient_shmmgr::shmget (const key_t key, const size_t size, const int shmflg){ syscall_printf ("shmget (key = 0x%016X, size = %u, shmflg = 0%o)", key, size, shmflg); client_request_shm request (key, size, shmflg); if (request.make_request () == -1 || request.error_code ()) { syscall_printf (("-1 [%d] = " "shmget (key = 0x%016X, size = %u, shmflg = 0%o)"), request.error_code (), key, size, shmflg); set_errno (request.error_code ()); return -1; } syscall_printf (("%d = shmget (key = 0x%016X, size = %u, shmflg = 0%o)"), request.shmid (), key, size, shmflg);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -