⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sysv_shmem.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * sysv_shmem.c *	  Implement shared memory using SysV facilities * * These routines represent a fairly thin layer on top of SysV shared * memory functionality. * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/port/sysv_shmem.c,v 1.44 2005/10/15 02:49:22 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include <errno.h>#include <signal.h>#include <unistd.h>#include <sys/file.h>#include <sys/stat.h>#ifdef HAVE_SYS_IPC_H#include <sys/ipc.h>#endif#ifdef HAVE_SYS_SHM_H#include <sys/shm.h>#endif#ifdef HAVE_KERNEL_OS_H#include <kernel/OS.h>#endif#include "miscadmin.h"#include "storage/ipc.h"#include "storage/pg_shmem.h"typedef key_t IpcMemoryKey;		/* shared memory key passed to shmget(2) */typedef int IpcMemoryId;		/* shared memory ID returned by shmget(2) */#define IPCProtection	(0600)	/* access/modify by user only */#ifdef SHM_SHARE_MMU			/* use intimate shared memory on Solaris */#define PG_SHMAT_FLAGS			SHM_SHARE_MMU#else#define PG_SHMAT_FLAGS			0#endifunsigned long UsedShmemSegID = 0;void	   *UsedShmemSegAddr = NULL;static void *InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size);static void IpcMemoryDetach(int status, Datum shmaddr);static void IpcMemoryDelete(int status, Datum shmId);static PGShmemHeader *PGSharedMemoryAttach(IpcMemoryKey key,					 IpcMemoryId *shmid);/* *	InternalIpcMemoryCreate(memKey, size) * * Attempt to create a new shared memory segment with the specified key. * Will fail (return NULL) if such a segment already exists.  If successful, * attach the segment to the current process and return its attached address. * On success, callbacks are registered with on_shmem_exit to detach and * delete the segment when on_shmem_exit is called. * * If we fail with a failure code other than collision-with-existing-segment, * print out an error and abort.  Other types of errors are not recoverable. */static void *InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size){	IpcMemoryId shmid;	void	   *memAddress;	shmid = shmget(memKey, size, IPC_CREAT | IPC_EXCL | IPCProtection);	if (shmid < 0)	{		/*		 * Fail quietly if error indicates a collision with existing segment.		 * One would expect EEXIST, given that we said IPC_EXCL, but perhaps		 * we could get a permission violation instead?  Also, EIDRM might		 * occur if an old seg is slated for destruction but not gone yet.		 */		if (errno == EEXIST || errno == EACCES#ifdef EIDRM			|| errno == EIDRM#endif			)			return NULL;		/*		 * Else complain and abort		 */		ereport(FATAL,				(errmsg("could not create shared memory segment: %m"),		  errdetail("Failed system call was shmget(key=%lu, size=%lu, 0%o).",					(unsigned long) memKey, (unsigned long) size,					IPC_CREAT | IPC_EXCL | IPCProtection),				 (errno == EINVAL) ?				 errhint("This error usually means that PostgreSQL's request for a shared memory "		  "segment exceeded your kernel's SHMMAX parameter.  You can either "						 "reduce the request size or reconfigure the kernel with larger SHMMAX.  "				  "To reduce the request size (currently %lu bytes), reduce "			   "PostgreSQL's shared_buffers parameter (currently %d) and/or "						 "its max_connections parameter (currently %d).\n"						 "If the request size is already small, it's possible that it is less than "						 "your kernel's SHMMIN parameter, in which case raising the request size or "						 "reconfiguring SHMMIN is called for.\n"		"The PostgreSQL documentation contains more information about shared "						 "memory configuration.",						 (unsigned long) size, NBuffers, MaxBackends) : 0,				 (errno == ENOMEM) ?				 errhint("This error usually means that PostgreSQL's request for a shared "				   "memory segment exceeded available memory or swap space. "				  "To reduce the request size (currently %lu bytes), reduce "			   "PostgreSQL's shared_buffers parameter (currently %d) and/or "						 "its max_connections parameter (currently %d).\n"		"The PostgreSQL documentation contains more information about shared "						 "memory configuration.",						 (unsigned long) size, NBuffers, MaxBackends) : 0,				 (errno == ENOSPC) ?				 errhint("This error does *not* mean that you have run out of disk space. "						 "It occurs either if all available shared memory IDs have been taken, "						 "in which case you need to raise the SHMMNI parameter in your kernel, "		  "or because the system's overall limit for shared memory has been "				 "reached.  If you cannot increase the shared memory limit, "		  "reduce PostgreSQL's shared memory request (currently %lu bytes), "			"by reducing its shared_buffers parameter (currently %d) and/or "						 "its max_connections parameter (currently %d).\n"		"The PostgreSQL documentation contains more information about shared "						 "memory configuration.",						 (unsigned long) size, NBuffers, MaxBackends) : 0));	}	/* Register on-exit routine to delete the new segment */	on_shmem_exit(IpcMemoryDelete, Int32GetDatum(shmid));	/* OK, should be able to attach to the segment */	memAddress = shmat(shmid, NULL, PG_SHMAT_FLAGS);	if (memAddress == (void *) -1)		elog(FATAL, "shmat(id=%d) failed: %m", shmid);	/* Register on-exit routine to detach new segment before deleting */	on_shmem_exit(IpcMemoryDetach, PointerGetDatum(memAddress));	/* Record key and ID in lockfile for data directory. */	RecordSharedMemoryInLockFile((unsigned long) memKey,								 (unsigned long) shmid);	return memAddress;}/****************************************************************************//*	IpcMemoryDetach(status, shmaddr)	removes a shared memory segment		*//*										from process' address spaceq		*//*	(called as an on_shmem_exit callback, hence funny argument list)		*//****************************************************************************/static voidIpcMemoryDetach(int status, Datum shmaddr){	if (shmdt(DatumGetPointer(shmaddr)) < 0)		elog(LOG, "shmdt(%p) failed: %m", DatumGetPointer(shmaddr));}/****************************************************************************//*	IpcMemoryDelete(status, shmId)		deletes a shared memory segment		*//*	(called as an on_shmem_exit callback, hence funny argument list)		*//****************************************************************************/static voidIpcMemoryDelete(int status, Datum shmId){	if (shmctl(DatumGetInt32(shmId), IPC_RMID, NULL) < 0)		elog(LOG, "shmctl(%d, %d, 0) failed: %m",			 DatumGetInt32(shmId), IPC_RMID);}/* * PGSharedMemoryIsInUse * * Is a previously-existing shmem segment still existing and in use? * * The point of this exercise is to detect the case where a prior postmaster * crashed, but it left child backends that are still running.	Therefore * we only care about shmem segments that are associated with the intended * DataDir.  This is an important consideration since accidental matches of * shmem segment IDs are reasonably common. */boolPGSharedMemoryIsInUse(unsigned long id1, unsigned long id2){	IpcMemoryId shmId = (IpcMemoryId) id2;	struct shmid_ds shmStat;#ifndef WIN32	struct stat statbuf;	PGShmemHeader *hdr;#endif	/*	 * We detect whether a shared memory segment is in use by seeing whether	 * it (a) exists and (b) has any processes are attached to it.	 */	if (shmctl(shmId, IPC_STAT, &shmStat) < 0)	{		/*		 * EINVAL actually has multiple possible causes documented in the		 * shmctl man page, but we assume it must mean the segment no longer		 * exists.		 */		if (errno == EINVAL)			return false;		/*		 * EACCES implies that the segment belongs to some other userid, which		 * means it is not a Postgres shmem segment (or at least, not one that		 * is relevant to our data directory).		 */		if (errno == EACCES)			return false;		/*		 * Otherwise, we had better assume that the segment is in use. The		 * only likely case is EIDRM, which implies that the segment has been		 * IPC_RMID'd but there are still processes attached to it.		 */		return true;	}	/* If it has no attached processes, it's not in use */	if (shmStat.shm_nattch == 0)		return false;	/*	 * Try to attach to the segment and see if it matches our data directory.	 * This avoids shmid-conflict problems on machines that are running	 * several postmasters under the same userid.  On Windows, which doesn't	 * have useful inode numbers, we can't do this so we punt and assume there	 * is a conflict.	 */#ifndef WIN32	if (stat(DataDir, &statbuf) < 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -