信号量

来源:互联网 发布:做地图的软件 编辑:程序博客网 时间:2024/06/15 12:16

一,信号量
信号量又称为信号灯,它是用来协调不同进程间的数据对象的,而最主要的应用是共享内存方式的进程间通信。本质上,信号量是一个计数器,它用来记录对某个资源(如共享内存)的存取状况。一般说来,为了获得共享资源,进程需要执行下列操作:
   (1) 测试控制该资源的信号量。
   (2) 若此信号量的值为正,则允许进行使用该资源。进程将信号量减1。
   (3) 若此信号量为0,则该资源目前不可用,进程进入睡眠状态,直至信号量值大于0,进程被唤醒,转入步骤(1)。
   (4) 当进程不再使用一个信号量控制的资源时,信号量值加1。如果此时有进程正在睡眠等待此信号量,则唤醒此进程。
   信号量是一个数据集合,用户可以单独使用这一集合的每个元素。要调用的第一个函数是semget,用以获得一个信号量ID。Linux下定义的信号量结构体:

struct semaphore {        spinlock_t     lock;        unsigned int   count;        struct list_head   wait_list;};

对信号量的操作只能是原子性的操作

二 ,工作原理
信号量只能进行两种操作等待和发送信号,即P(sv)和V(sv),他们的行为是这样的:
P(sv):如果sv的值大于零,就给它减1;如果它的值为零,就挂起该进程的执行 。
V(sv):如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,就给它加1.

1.semget()函数

int semget(key_t key,int nsems,int semflg); 功能描述获取关联的信号量集标识。信号量集被建立的情况有两种:1.如果值是IPC_PRIVATE。2.或者值不是IPC_PRIVATE,并且所对应的信号量集不存在,同时标志中指定IPC_CREAT。当调用semget创建一个信号量时,他的相应的semid_ds结构被初始化。ipc_perm中各个量被设置为相应值

2.semctl()函数

int semctl(int sem_id, int sem_num, int command, ...)

3.semop()函数

int semop(int sem_id, struct sembuf *sem_opa, size_t num_sem_ops)sembuf结构的定义如下:struct sembuf{  short sem_num;//除非使用一组信号量,否则它为0short sem_op;//信号量在一次操作中需要改变的数据,通常是两个数,一个是-1,即P(等待)操作,一个是+1,即V(发送信号)操作。short sem_flg;//通常为SEM_UNDO,使操作系统跟踪信号,并在进程没有释放该信号量而终止时,操作系统释放信号量}; 

三,回滚(ROLLBACK)和撤销(UNDO)

回滚和前滚是保证Oracle数据库中的数据处于一致性状态的重要手段。

在9i版本以前 Oracle使用数据库中的回滚段来实现未提交数据或因系统故障导致实例崩溃时进行回滚操作 每一个表空间需要创建回滚段,各个表空间对回滚段实现各自的管理 在9i及后续版本 提供了一种新的回滚数据的管理方式,即使用Oracle自动管理的撤销(Undo)表空间 自动撤销管理表空间统一管理所有DML的回滚操作,简化了对于回滚工作的管理 在9i,10g中的回滚段仅仅用作保留向后兼容 撤销段代替了原有版本中的回滚段,因此本文所有描述均使用撤销

撤销的实质意味着将所作的修改退回到修改前的状态,即倒退所有DML语句

对于任何DML操作而言,必须同时处理数据块和撤销块,并且还会生成重做信息 在ACID中,A、C、I要求生成撤销,D则要求生成重做 INSERT: 撤销段记录插入记录的rowid,如果需要撤销,则根据rowid将该记录删除即可 UPDATE: 撤销段记录被更新字段的原始值,撤销时将原始值覆盖新值即可 DELETE: 撤销段记录整行的数据,撤销时执行反向操作将该记录插入原表 UNDO段中的内容如下: 数据为修改之前的副本 从每个改变数据的事务中获得 在事务结束前一直被保留

UNDO段中数据的作用: 用于回滚操作 读一致性和闪回查询 用于事务失败时的恢复

UNDO段与事务: 一个事物的启动,Oracle将为其分配仅仅一个UNDO段,若该段用完,则Oracle会自动为该UNDO段添加另一个区间(extent) 一个UNDO段能够同时为多个事务服务

UNDO段与UNDO表空间: UNDO段中的内容存储在UNDO表空间 任意给定时刻只能使用一个UDNO表空间 UNDO表空间必须被创建为持久的、本地管理、可自动扩展的表空间 正在使用的UNDO表空间不能撤销或删除 UNDO表空间使用循环写的方式,与联机日志文件写相似,不同的是UNDO中可以设置了undo_retention 保留时间

UNDO段的两种管理方式: AUTO 自动管理(推荐) MANUAL 手动管理(仅保留)

作者:qq_35032155 发表于2017/6/9 16:58:42 原文链接
阅读:111 评论:0 查看评论
 [原]进程间通信——共享内存

一, 概念 共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对 其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用, 来达到进程间的同步及互斥。 二,特点 1.共享内存就是允许两个不相关的进程访问同一个逻辑内存; 2.共享内存是在两个正在运行的进程之间共享和传递数据的一种最有效的方式; 3.不同进程之间共享的内存通常安排为同一段物理内存; 4.共享内存不提供任何互斥和同步机制,一般用信号量对临界资源进行保护; 5.接口简单

三, 所有进程间通信的特点

1)管道

管道分为有名管道和无名管道 无名管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用.进程的亲缘关系一般指的是父子关系。无明管道一般用于两个不同进程之间的通信。当一个进程创建了一个管道,并调用fork创建自己的一个子进程后,父进程关闭读管道端,子进程关闭写管道端,这样提供了两个进程之间数据流动的一种方式。 有名管道也是一种半双工的通信方式,但是它允许无亲缘关系进程间的通信。

2)信号量

信号量是一个计数器,可以用来控制多个线程对共享资源的访问.,它不是用于交换大批数据,而用于多线程之间的同步.它常作为一种锁机制,防止某进程在访问资源时其它进程也访问该资源.因此,主要作为进程间以及同一个进程内不同线程之间的同步手段.

3)消息队列

消息队列是消息的链表,存放在内核中并由消息队列标识符标识.消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限等特点.消息队列是UNIX下不同进程之间可实现共享资源的一种机制,UNIX允许不同进程将格式化的数据流以消息队列形式发送给任意进程.对消息队列具有操作权限的进程都可以使用msget完成对消息队列的操作控制.通过使用消息类型,进程可以按任何顺序读信息,或为消息安排优先级顺序.

4)共享内存

共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问.共享内存是最快的IPC(进程间通信)方式,它是针对其它进程间通信方式运行效率低而专门设计的.它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步与通信.

四 , 共享内存的代码实现 1. semget函数 创建一个新信号量或取得一个已有信号量

int semget(key_t key, int num_sems, int sem_flags);

2.semctl函数 直接控制信号量信息

int semctl(int sem_id, int sem_num, int command, ...);

3.shmat()函数
第一次创建完共享内存时,它还不能被任何进程访问,shmat函数的作用就是用来启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间。

shm_id:由shmget函数返回的共享内存标识。shm_addr:指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址。shm_flg:是一组标志位,通常为0。

4.shmdt()函数
该函数用于将共享内存从当前进程中分离。注意,将共享内存分离并不是删除它,只是使该共享内存对当前进程不再可用。


原创粉丝点击