linux第11天

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

在此之前,有个管道问题

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;
}

  

时间: 2024-08-12 01:25:56

linux第11天的相关文章

Linux 0.11中write实现

看了一下Linux 0.11版本write的实现,首先它在标准头文件unistd.h中有定义 int write(int fildes, const char * buf, off_t count); 接下来看write.c /* * linux/lib/write.c * * (C) 1991 Linus Torvalds */ #define __LIBRARY__ #include <unistd.h> //定义write的实现 _syscall3(int,write,int,fd,co

Linux 0.11 中字符设备的使用

Linux 0.11 字符设备的使用 一.概述 本文自顶向下一步步探索字符设备的读写是怎么完成的.通常我们在Linux应用程序中用open.read.write对各种类型的文件进行操作.我们可以从键盘输入,然后命令行窗口会显示你的输入,有输出的话则命令行窗口会显示输出.为什么所有的设备在Linux中都被看成是一个个文件,可以通过统一的read.write直接进行读写?文件句柄与终端设备有什么关联?为什么Linux允许多个控制终端登录?tty又是什么东西?读写时将发生哪些硬件中断,驱动程序是怎么回

基于 Docker 快速构建 Linux 0.11 实验环境

by Falcon of TinyLab.org 2015/05/02 简介 五分钟内搭建 Linux 0.11 的实验环境介绍了如何快速构建一个 Linux 0.11 实验环境. 本文介绍如何快速构建一个独立于宿主机的 Linux 0.11 实验环境,该实验环境可以用于任何操作系统的宿主开发机,将非常方便各类学生学习 Linux 0.11,本文只介绍 Ubuntu.在 Windows 和 Mac 下可以用 VirtualBox + Boot2Docker 来启动. 下文要求已经安装 git 和

Linux系统管理11——系统安全及应用

Linux系统管理11--系统安全及应用 一.基本安全措施 1.系统账号清理 (1)将非登录用户的shell设为/sbin/nologin ·方法一: usermod -s ·方法二: chsh命令,交互式修改 ·方法三: chsh -s 示例: 除了上述三种方法,也可以直接vi编辑/etc/passwd文件进行修改. (2)锁定长期不使用的账号 ·方法一: passwd -l  (将在密文前增加2个"!")解锁 passwd -u 查看passwd -S ·方法二: usermod

Linux 0.11下信号量的实现和应用

Linux 011下信号量的实现和应用 生产者-消费者问题 实现信号量 信号量的代码实现 关于sem_wait和sem_post sem_wait和sem_post函数的代码实现 信号量的完整代码 实现信号量的系统调用 测试用的应用程序的实现 Linux 0.11下信号量的实现和应用 1.生产者-消费者问题 从一个实际的问题:生产者与消费者出发,谈一谈为什么要有信号量?信号量用来做什么? 问题描述:现在存在一个文件”.\buffer.txt”作为一个共享缓冲区,缓冲区同时最多只能保存10个数.现

ubuntn 内核升级到LINUX v4.11.8:

升级到LINUX v4.11.8: http://kernel.ubuntu.com/~kernel-ppa/mainline/v4.11.8/linux-headers-4.11.8-041108_4.11.8-041108.201706290836_all.deb http://kernel.ubuntu.com/~kernel-ppa/mainline/v4.11.8/linux-headers-4.11.8-041108-generic_4.11.8-041108.20170629083

SUSE Linux Enterprise 11 SP4 系统安装

[1] Insert installation media in CD/DVD drive and restart your computer. Follwoing screen is shown and Click "Installation" to do it. [2] Select your language and keyboard layouts.And also check a box "I Agree to the Lisence Terms" to

在SUSE Linux Enterprise 11 SP1上用UDEV SCSI配置ASM

1. 编辑/etc/scsi_id.config文件,如果该文件不存在,则创建该文件,添加如下行: options=–whitelisted –replace-whitespace 2. 获取需要绑定为ASM Disk的磁盘uuid,比如我们要使用/dev/sdc和/dev/sdd作为ASM磁盘,那么: # /lib/udev/scsi_id –whitelisted –replace-whitespace –device=/dev/sdc 1ATA_VBOX_HARDDISK_VB36a9e5

【转载】每天一个linux命令(11):nl命令

转载至:http://www.cnblogs.com/peida/archive/2012/11/01/2749048.html nl命令在linux系统中用来计算文件中行号.nl 可以将输出的文件内容自动的加上行号!其默认的结果与 cat -n 有点不太一样, nl 可以将行号做比较多的显示设计,包括位数与是否自动补齐 0 等等的功能. 1.命令格式: nl [选项]... [文件]... 2.命令参数: -b  :指定行号指定的方式,主要有两种: -b a :表示不论是否为空行,也同样列出行

1.9 使用PuTTY远程连接Linux 1.10 使用xshell连接Linux 1.11 PuT

1.9 使用PuTTY远程连接Linux1.10 使用xshell连接Linux1.11 PuTTY密钥认证1.12 xshell密钥认证 笔记: VMwork快照:便于恢复 使用ssh服务实现远程登录linux系统功能. Putty下载网址:https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html3.Host Name填写远程的机器的IP port是端口(可以自定义) Xsell下载后的连接方式 通过xsheel和putty生