共享内存进程间通信机制主要用于实现进程间大量的数据传输,下图所示为进程间使用共享内存实现大量数据传输的示意图:
640
共享内存是在内存中单独开辟的一段内存空间,这段内存空间有自己特有的数据结构,包括访问权限、大小和最近访问的时间等。该数据结构定义如下:
from /usr/include/linux/shm.h
struct shmid_ds {
struct ipc_perm shm_perm/* operation perms *** 作权限 */
int shm_segsz/* size of segment (bytes) 段长度大小 */
__kernel_time_t shm_atime/* last attach time 最近attach时间 */
__kernel_time_t shm_dtime/* last detach time 最近detach时间 */
__kernel_time_t shm_ctime/* last change time 最近change时间 */
__kernel_ipc_pid_t shm_cpid/* pid of creator 创建者pid */
__kernel_ipc_pid_t shm_lpid/* pid of last operator 最近 *** 作pid */
unsigned short shm_nattch/* no. of current attaches */
unsigned short shm_unused/* compatibility */
void *shm_unused2/* ditto - used by DIPC */
void *shm_unused3/* unused */|
}
两个进程在使用此共享内存空间之前,需要在进程地址空间与共享内存空间之间建立联系,即将共享内存空间挂载到进程中。
系统对共享内存做了以下限制:
#define SHMMAX 0x2000000 /* max shared seg size (bytes) 最大共享段大小 */
#define SHMMIN 1 /* min shared seg size (bytes) 最小共享段大小 */
#define SHMMNI 4096 /* max num of segs system wide */
#define SHMALL (SHMMAX/getpagesize()*(SHMMNI/16))|
define SHMSEG SHMMNI /* max shared segs per process */
Linux 共享内存管理
1.创建共享内存
#include <sys/ipc.h>#include <sys/shm.h>
/*
* 第一个参数为 key 值,一般由 ftok() 函数产生
* 第二个参数为欲创建的共享内存段大小(单位为字节)
* 第三个参数用来标识共享内存段的创建标识
*/
int shmget(key_t key, size_t size, int shmflg)
2.共享内存控制
#include <sys/ipc.h>#include <sys/shm.h>
/*
* 第一个参数为要 *** 作的共享内存标识符
* 第二个参数为要执行的 *** 作
* 第三个参数为 shmid_ds 结构的临时共享内存变量信息
*/
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
3.映射共享内存对象
系统调用 shmat() 函数实现将一个共享内存段映射到调用进程的数据段中,并返回内存空间首地址,其函数声明如下:
#include <sys/types.h>
#include <sys/shm.h>
/*
* 第一个参数为要 *** 作的共享内存标识符
* 第二个参数用来指定共享内存的映射地址,非0则为此参数,为0的话由系统分配
* 第三个参数用来指定共享内存段的访问权限和映射条件
*/
void *shmat(int shmid, const void *shmaddr, int shmflg)
4.分离共享内存对象
在使用完毕共享内存空间后,需要使用 shmdt() 函数调用将其与当前进程分离。函数声明如下:
#include <sys/types.h>
#include <sys/shm.h>
/*
* 参数为分配的共享内存首地址
*/
int shmdt(const void *shmaddr)
共享内存在父子进程间遵循的约定
1.使用 fork() 函数创建一个子进程后,该进程继承父亲进程挂载的共享内存。
2.如果调用 exec() 执行一个新的程序,则所有挂载的共享内存将被自动卸载。
3.如果在某个进程中调用了 exit() 函数,所有挂载的共享内存将与当前进程脱离关系。
程序实例
申请一段共享内存,父进程在首地址处存入一整数,子进程读出。
#include
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include
#include
#define SHM_SIZE 1024
int main()
{
int shm_id, pid
int *ptr = NULL
/* 申请共享内存 */
shm_id = shmget((key_t)1004, SHM_SIZE, IPC_CREAT | 0600)
/* 映射共享内存到进程地址空间 */
ptr = (int*)shmat(shm_id, 0, 0)
printf("Attach addr is %p ", ptr)
*ptr = 1004
printf("The Value of Parent is : %d ", *ptr)
if((pid=fork()) == -1){
perror("fork Err")
exit(0)
}
else if(!pid){
printf("The Value of Child is : %d ", *ptr)
exit(0)
}else{
sleep(1)
/* 解除映射 */
shmdt(ptr)
/* 删除共享内存 */
shmctl(shm_id, IPC_RMID, 0)
}
return 0
}
输出结果:
640
我也是新来的,不过对UNIX/LINUX, ORACLE, J2EE都非常有兴趣,以后希望大家互相交流特写这篇安装教学作为见面礼
在Linux下,不更改Kernel也可能可以安装,步骤跟SOLARIS相同
但在SOLARIS下就一定要改内核参数了,我下面的教学就是针对Solaris Sparc/Intel`
在/etc/system最后加入这些:
set shmsys:shminfo_shmmax=4294967295
set shmsys:shminfo_shmmin=1
set shmsys:shminfo_shmmni=100
set shmsys:shminfo_shmseg=10
set semsys:seminfo_semmns=2000
set semsys:seminfo_semmsl=1000
set semsys:seminfo_semmni=100
set semsys:seminfo_semopm=100
set semsys:seminfo_semvmx=32767
unset TWO_TASK
重新启动,添加GROUP
groupadd dba
groupadd oinstall
然后添加用户
useradd -c "Oracle DBA" -d /home/oracle -g oinstall -G dba -m -u 300
passwd oracle
mkdir /var/opt/oracle
cd /var/opt/oracle
mkdir u01
mkdir u02
mkdir u03
mkdir u04
(Oracle推荐使用这种4DISK的模式来提高性能和可靠性,你不需要4DISK,不过可以分布到四个文件夹或分区)
ln -s /var/opt/oracle/u01 /u01
ln -s /var/opt/oracle/u02 /u02
ln -s /var/opt/oracle/u03 /u03
ln -s /var/opt/oracle/u04 /u04
chown oracle:oinstall /u01
chown oracle:oinstall /u02
chown oracle:oinstall /u03
chown oracle:oinstall /u04
chmod 755 /u01
chmod 755 /u02
chmod 755 /u03
chmod 755 /u04
登陆到oracle
修改.profile
加入
ORACLE_BASE=/u01/app/oracle
ORACLE_HOME=$ORACLE_BASE/product/8.1.7
ORACLE_SID=orcl
DBA=$ORACLE_BASE/admin
PATH=$PATH:$ORACLE_HOME/bin:/usr/local/bin
export ORACLE_BASE ORACLE_HOME ORACLE_SID DBA PATH
退出后重新登陆就可以安装了,这里的SID我命名为ORCL,你可以任意更改,当然用户和组也一样,安装时会问你DBA的组,选DBA就可以了
剩下的安装就应该很顺利了,完全按照ORACLE说的就可以.
!!!!!在Oracle 8i for Solaris Intel中有一个严重的BUG,会导致不能完成安装
Oracle建立/var/opt/oracle/oratab
但dbstart却去/etc/oratab寻找,所以导致startdb启动失败
ln -s /var/opt/oracle/oratab /etc/oratab
就可以解决这个问题
下面介绍如何在开机时自动启动ORACLE
在/etc/init.d下建立dbora
#!/bin/sh
ORA_HOME=/u01/app/oracle/product/8.1.7
ORA_OWNER=oracle
if [ ! -f $ORA_HOME/bin/dbstart ]
then
echo "Oracle startup: cannot start"
exit
fi
case "$1" in
'start') # Start Oracle Database and Net8 listener
su - $ORA_OWNER -c "$ORA_HOME/bin/dbstart" &
su - $ORA_OWNER -c "$ORA_HOME/bin/lsnrctl start" &
su - $ORA_OWNER -c "ORA_HOME/Apache/Apache/bin/apachectl start" &
'stop') # Stop Oracle Database and Net8 listener
su - $ORA_OWNER -c "$ORA_HOME/bin/dbshut" &
su - $ORA_OWNER -c "$ORA_HOME/bin/lsnrctl stop" &
su - $ORA_OWNER -c "ORA_HOME/Apache/Apache/bin/apachectl stop" &
esac
然后作一个连接
ln -s /etc/init.d/dbora /etc/rc2.d/S99dbora
ln -s /etc/init.d/dbora /etc/rc0.d/K10dbora
打开/var/opt/oracle/oratab
把N改为Y
orcl:/u01/app/oracle/product/8.1.7:[color=#DC143C]Y[/color]
这里,我用ORACLE用户运行APACHE,在安全上有很大漏洞,你可以换成其他没有权限的用户,APACHE使用的端口是7777,你如果要换成80端口,那还要作很多改动,这里不介绍
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)