今天主要学习了共享内存和信号量

在此之前,有个管道问题

ls | grep a

整句话的意思是将ls输出到管道的写端,而流通到另一端的读端,grep a则是从管道的读端读取相关数据,再做筛选

共享内存

int shmget(key_t key, size_t size, int flag);

key: 标识符的规则
size:共享存储段的字节数
flag:读写的权限 0666 | O_CREAT
返回值:成功返回共享存储的id,失败返回-1

shmat
void *shmat(int shmid, const void *shmaddr, int flag);
shmid:共享存储的id
shmaddr:一般为0,表示连接到由内核选择的第一个可用地址上,否则,如果flag没有指定SHM_RND,则连接到addr所指定的地址上,如果flag为SHM_RND,则地址取整
flag:如前所述,一般为0
返回值:如果成功,返回共享存储段地址,出错返回-1

shmaddr为NULL,核心自动选择一个地址
shmaddr不为NULL且shmflg无SHM_RND标记,则以shmaddr为连接地址。
shmaddr不为NULL且shmflg设置了SHM_RND标记,则连接的地址会自动向下调整为SHMLBA的整数倍。公式:shmaddr - (shmaddr % SHMLBA)
shmflg=SHM_RDONLY,表示连接操作用来只读共享内存

shmdt

行为与shmat相反,取消共享内存映射

shmctl函数
  功能:用于控制共享内存
  原型
  int shmctl(int shmid, int cmd, struct shmid_ds  *buf);
  参数
  shmid:由shmget返回的共享内存标识码
  cmd:将要采取的动作(有三个可取值)
  buf:指向一个保存着共享内存的模式状态和访问权限的数据结构
  返回值:成功返回0;失败返回-1

共享内存的创建与操作

	int shmid = shmget(0x159357, 4, 0666 | IPC_CREAT);
if (shmid < 0)
perror("shmget"); void *p = NULL;
p = shmat(shmid, NULL, 0);
(*(int *)p) = 0; shmdt(p);

  

信号量

信号量可以看成一个结构体,里面包含两个字段同数据.

1.可以使用的资源数据.当资源数用完,没有资源释放,再次访问资源内核将阻塞进程

2.被阻塞的进程队列.

struct semaphore
{
  int value;
  pointer_PCB queue;
}

信号量值含义
S>0:S表示可用资源的个数
S=0:表示无可用资源,无等待进程
S<0:|S|表示等待队列中进程个数

P原语
P(s)
{
  s.value = s.value--;
  if (s.value< 0)
  {
    该进程状态置为等待状状态
    将该进程的PCB插入相应的等待队列s.queue末尾
  }
}

V原语
V(s)
{
  s.value = s.value++;
  if (s.value< =0)
  {
    唤醒相应等待队列s.queue中等待的一个进程
    改变其状态为就绪态
    并将其插入就绪队列
  }
}

semget函数
功能:用来创建和访问一个信号量集
原型
int semget(key_t key, int nsems, int semflg);
参数
key: 信号集的名字
nsems:信号集中信号量的个数
semflg: 由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的
返回值:成功返回一个非负整数,即该信号集的标识码;失败返回-1

shmctl函数
功能:用于控制信号量集
原型
int semctl(int semid, int semnum, int cmd, ...);
参数
semid:由semget返回的信号集标识码
semnum:信号集中信号量的序号
cmd:将要采取的动作(有三个可取值)
最后一个参数根据命令不同而不同
返回值:成功返回0;失败返回-1

semop函数
功能:用来创建和访问一个信号量集
原型
int semop(int semid, struct sembuf *sops, unsigned nsops);
参数
semid:是该信号量的标识码,也就是semget函数的返回值
sops:是个指向一个结构数值的指针
nsops:信号量的个数
返回值:成功返回0;失败返回-1

semop函数续
sembuf结构体:
struct sembuf {
  short sem_num;
  short sem_op;
  short sem_flg;
};
sem_num是信号量的编号。
sem_op是信号量一次PV操作时加减的数值,一般只会用到两个值,一个是“-1”,也就是P操作,等待信号量变得可用;另一个是“+1”,也就是我们的V操作,发出信号量已经变得可用
sem_flag的两个取值是IPC_NOWAIT或SEM_UNDO,一般取0

封装好的信号操作函数

union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
}; int semCreateOrGet(key_t key)
{
int semid = 0;
semid = semget(key, 1, 0666 | IPC_CREAT);
if (semid < 0)
ERR_EXIT("semget"); return semid;
} int semSetValue(int semid, int val)
{
int ret = 0;
union semun su;
su.val = val;
ret = semctl(semid, 0, SETVAL, su);
return ret; } int semGetValue(int semid)
{
int ret = 0;
union semun su;
ret = semctl(semid, 0, GETVAL, su);
printf("目前资源数为%d\n", su.val);
return ret; } int sem_p(int semid)
{
int ret = 0;
struct sembuf sbuf = { 0, -1, 0 };
ret = semop(semid, &sbuf, 1);
return ret;
} int sem_v(int semid)
{
int ret = 0;
struct sembuf sbuf = { 0, 1, 0 };
ret = semop(semid, &sbuf, 1);
return ret;
}

  

linux第11天 共享内存和信号量的更多相关文章

  1. 浅析Linux下进程间通信:共享内存

    浅析Linux下进程间通信:共享内存 共享内存允许两个或多个进程共享一给定的存储区.因为数据不需要在客户进程和服务器进程之间复制,所以它是最快的一种IPC.使用共享内存要注意的是,多个进程之间对一给定 ...

  2. 第三十三章 System V共享内存与信号量综合

    用信号量解决生产者.消费者问题 实现shmfifo ip.h #ifndef _IPC_H #define _IPC_H #include <unistd.h> #include < ...

  3. C实现进程间通信(管道; 共享内存,信号量)

    最近学习了操作系统的并发:以下是关于进程间实现并发,通信的两个方法. 例子: 求100000个浮点数的和.要求: (1)随机生成100000个浮点数(父进程). (2)然后创建4个后代进程,分别求25 ...

  4. Linux 进程间通信(管道、共享内存、消息队列、信号量)

           进程通信 : 不同进程之间传播或交换信息    为什么要进程通信呢? 协同运行,项目模块化 通信原理 : 给多个进程提供一个都能访问到的缓冲区. 根据使用场景,我们能划分为以下几种通信 ...

  5. 8.7 进程间的通讯:管道、消息队列、共享内存、信号量、信号、Socket

    进程间的通讯 进程间为什么需要通讯? 共享数据.数据传输.消息通知.进程控制 进程间的通讯有哪些类型? 首先,联系前面讲过的知识,进程之间的用户地址空间是相互独立的,不能进行互相访问,但是,内核空间却 ...

  6. Linux环境进程间通信(五): 共享内存(下)

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...

  7. Linux环境进程间通信(五): 共享内存(上)

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...

  8. ubuntu linux c学习笔记----共享内存(shmget,shmat,shmdt,shmctl)

    shmget int shmget(key_t key, size_t size, int flag); key: 标识符的规则 size:共享存储段的字节数 flag:读写的权限 返回值:成功返回共 ...

  9. Linux IPC System V 共享内存

    模型 #include<sys/types.h> #include<sys/ipc.h> #include<sys/shm.h> ftok() //获取key值 s ...

随机推荐

  1. 在Vista或更高版本Windows系统中, 获取超大图标的办法

    这几天写个小东西, 需要获取系统正在运行的程序图标, 一般来说32*32就足够了, 不过既然Win7能够支持超大图标(256*256), 咱们也需要与时俱进, 说不定什么时候遇到个变态客户就有这要求了 ...

  2. TWICImage.SaveToStream内存泄漏的解决办法

    这个BUG从2010到XE5一直没改.....只能自己写个函数来搞了 uses ActiveX; procedure WICImageSaveToStream(AWICImage: TWICImage ...

  3. 【Android测试】【第二节】ADB——无线模式

    ◆版权声明:本文出自胖喵~的博客,转载必须注明出处.      转载请注明出处:http://www.cnblogs.com/by-dream/p/4635782.html 啰嗦两句啊.本来以为adb ...

  4. C/C++ 获取汉字拼音

    参考文章:http://blog.csdn.net/thenile/article/details/6318521 在参考文章的基础上,去掉了代码中C++特有的语法和数据类型,用纯C语言实现了获取汉字 ...

  5. [LeetCode]题解(python):078 Subsets

    题目来源 https://leetcode.com/problems/subsets/ Given a set of distinct integers, nums, return all possi ...

  6. 解决在VMware中安装64位系统时“此主机具有虚拟化支持能力的,但虚拟化技术被禁用”的方法

    您已经配置此虚拟机使用64位客户操作系统.然而,64位操作系统不可用.此主机具有虚拟化支持能力的,但虚拟化技术被禁用.这通常是因为虚拟化技术已经在BIOS /固件设置或禁用或主机没有权限改变此设置. ...

  7. http://blog.csdn.net/fw0124/article/details/48280083

    http://blog.csdn.net/fw0124/article/details/48280083

  8. Linux 中的零拷贝技术,第 2 部分

    技术实现 本系列由两篇文章组成,介绍了当前用于 Linux 操作系统上的几种零拷贝技术,简单描述了各种零拷贝技术的实现,以及它们的特点和适用场景.第一部分主要介绍了一些零拷贝技术的相关背景知识,简要概 ...

  9. android关于The connection to adb is down, and a severe error has occured.这个问题的解决办法

    有时在打开模拟器的时候会出现The connection to adb is down, and a severe error has occured.这个问题,这个问题的解决办法有两个: 方法一:找 ...

  10. C# 调用C++动态链接库

    项目中需要调用一个 USB接口的设备,用WPF写上位机,设备提供了C++的动态链接库. 按照已找到的资料,将 .dll  .h  和相关依赖项都放在 程序的运行目录中,执行,会报错,找不到“XXX.d ...