- 浏览: 270740 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
AndMacLinuXp:
试了下,不错!
printk内核调试 -
klose:
我引用你的文章,并做了简单的分析:这里贴出url:http:/ ...
linux系统调用fork, vfork, clone -
klose:
你上面提到的问题:free的问题。首先你可能疏忽了,stack ...
linux系统调用fork, vfork, clone -
qwe_rt:
HI ,非常nice的文章,在阅读过程中,我发现我的ubunt ...
linux手动添加开机启动的服务 -
suifeng:
谢谢分享, 受用中.
shell编程分支,循环
前面我们谈到过管道,消息队列。我们可以使用他们可以解决了2个进程直接通信的问题,其实还有一个办法是共享内存,具体函数我没给出,大家可以自己查询资料。管道,消息队列除了提供进程通信的解决办法外,他还给我们提供了一个额外的功能,那就是多个进程对临界资源的共享问题。(共享内存没有,需要自己实现对资源的互斥操作)
无论是管道还是报文,发送方在写满的时候都会被阻塞,接受方在空的时候也会被阻塞。所以我们没有看到对同一个管道或者报文读写时候要加上额外的代码解决多个进程对资源共享产生的问题。但有些时候我们对某些资源操作需要实现互斥操作,不允许2个以上的进程同时操作资源,其实这个在JAVA里面由于封装,我们使用一个关键字就可以解决了(关键字是那个不记得了,或许我该GOOGLE下),JAVA是高层的实现,操作系统底层是通过信号量来对这一功能完成的。LINUX中提供的系统调用是3个函数semget, semop和semctl
semget:用于创建或者搜索信号量,这个网址中有详细说明http://club.cn.yahoo.com/bbs/threadview/1200062866_111__pn1.html
semop:对信号量的操作http://club.cn.yahoo.com/bbs/threadview/1200062866_112__pn1.html
semctl:对信号量的控制http://club.cn.yahoo.com/bbs/threadview/1200062866_109__pn1.html
下面我们写个代码,2个进程公用一个输出终端,通过printf向我们打印一些语句,其中父进程的打印语句看起来像这样
printf("this is father start\n");
sleep(1);
printf("father\n");
printf("father\n");
printf("father\n");
printf("father\n");
sleep(1);
printf("father\n");
printf("father end\n");
其中子进程看起来像这样:
printf("this is child start\n");
sleep(1);
printf("child\n");
printf("child\n");
printf("child\n");
printf("child\n");
sleep(1);
printf("child\n");
printf("child end\n");
这2段代码我都放在for(i = 0; i < 10; i++)里面,这样才能看出效果可能一次只是偶然(当然10次也可能是偶然,不过概率要小很多了),如果我们不加限制,他们最后结果会是这样
this is father start
child
child end
this is child start
father
father
father
father
child
child
child
child
father
father end
this is father start
child
child end
我们要实现的情况是在执行
printf("this is father start\n");
sleep(1);
printf("father\n");
printf("father\n");
printf("father\n");
printf("father\n");
sleep(1);
printf("father\n");
printf("father end\n");代码时候不允许执行子进程打印,同样在执行子进程的代码时候也不允许父进程的打印结果来干扰,最后显示在看完程序后给出。
[root@liumengli signal]# cat father.c (父进程代码)
#include "sys/types.h"
#include "linux/sem.h"
#include "errno.h"
#include "stdio.h"
#include "stdlib.h"
#include "fcntl.h"
#include "asm/user.h"
#include "sys/syscall.h"
#include "sys/wait.h"
#include "unistd.h"
#define MAXSEM 5
int my_sem;
int main() {
struct sembuf P, V;
union semun arg;
key_t key;
key = ftok("/", 4);
if(key == -1) {
printf("create key failed\n");
exit(1);
}
//create sem
my_sem = semget(key, 1, IPC_CREAT); //开始创建信号量,函数具体说明可以参照我给的网址
//init sem
arg.val = 0;
if(semctl(my_sem, 0, SETVAL, arg) == -1) {
printf("init sem error\n");
semctl(my_sem, 0, IPC_RMID);
exit(1);
}
arg.val = 1;
semctl(my_sem, 0, SETVAL, arg);//将信号量中0号信号的资源数设置成1
//init P and V 初始化PV操作,具体参照可以看我给的网址
V.sem_num = 0;
V.sem_op = 1;
V.sem_flg = SEM_UNDO;
P.sem_num = 0;
P.sem_op = -1;
P.sem_flg = SEM_UNDO;
pid_t child = fork();
if(child == 0) {
execl("/process_communicate/ipc/signal/child", "child", NULL);//执行子程序
}
int i;
for(i = 0; i < 10; i++) {
semop(my_sem, &P, 1); //开始之前执行P操作
printf("this is father start\n");
sleep(1);
printf("father\n");
printf("father\n");
printf("father\n");
printf("father\n");
sleep(1);
printf("father\n");
printf("father end\n");
semop(my_sem, &V, 1);//结束后记得V操作
}
semctl(my_sem, 0, IPC_RMID);
exit(0);
}
[root@liumengli signal]# cat child.c
#include "sys/types.h"
#include "linux/sem.h"
#include "errno.h"
#include "stdio.h"
#include "stdlib.h"
#include "fcntl.h"
#define MAXSEM 5
int my_sem;
int main() {
struct sembuf P, V;
key_t key;
key = ftok("/", 4);
if(key == -1) {
printf("create key failed\n");
exit(1);
}
//create sem
my_sem = semget(key, 1, IPC_EXCL);//搜索信号量
//init P and V 初始化PV操作,为什么不初始化信号量,大家可以看到我是在父进程初始完毕信号量才启动子进程的
V.sem_num = 0;
V.sem_op = 1;
V.sem_flg = SEM_UNDO;
P.sem_num = 0;
P.sem_op = -1;
P.sem_flg = SEM_UNDO;
int i;
for(i = 0; i < 10; i++) {
semop(my_sem, &P, 1);//开始之前的P操作
printf("this is child start\n");
sleep(1);
printf("child\n");
printf("child\n");
printf("child\n");
printf("child\n");
sleep(1);
printf("child\n");
printf("child end\n");
semop(my_sem, &V, 1);//结束后的V操作
}
exit(0);
}
[root@liumengli signal]# ./father
this is child start
child
child
child
child
child
child end
this is father start
father
father
father
father
father
father end
.....
我只截获了一小段,这次文章够长了,太长就不贴了。从运行结果我们实现对输出终端的互斥操作。
发表评论
-
linux下挂在windows共享文件夹
2012-05-06 12:53 886smbmount //nas/xxxx /mnt/nas -o ... -
进程组 对话期
2010-04-16 16:12 1408为了便于进程控制,于是就有了进程组,对话期的概念。 进 ... -
感谢你教会我如何提问-《提问的智慧》
2009-01-12 11:25 1454转自:http://linux.chinaunix ... -
linux手动添加开机启动的服务
2009-01-02 14:48 7201如果你只是想知道如何 ... -
进程通行之报文消息队列
2008-12-04 17:39 1416报文和消息队列又是进 ... -
信号和信号处理
2008-11-26 16:09 3343信号同样是用于进程通 ... -
命名管道实现样例
2008-11-18 17:41 1286[root@liumengli name_pipe]# mkn ... -
linux中的管道实现和管道
2008-11-14 17:52 12981inux的shell中有个很常用的东西管道,很多人认为他是sh ... -
文件访问权限和安全
2008-10-28 18:02 1238打开文件,读取内容或 ... -
printk内核调试
2008-10-15 17:07 9451首先阐明一点,我调试的目的是为了学习,看看内核代码是如何运行, ... -
linux内核编译
2008-10-07 17:36 1966这是调试linux内核的必要步骤,虽然很麻烦,而且容易出错(所 ... -
linux文件系统
2008-10-06 11:08 1015文件系统是一个比较模糊的名词,文件也是一个比较模糊的名词。狭义 ... -
linux内核书籍下载
2008-09-25 11:47 2184学习内核代码之前,需要有以下一些基础: 1.linux系统管理 ... -
nanosleep函数
2008-09-24 17:36 3378int nanosleep(const struct ti ... -
linux进程调度政策
2008-09-23 11:45 1588进程调度政策就是调度系统种哪一个进程来CPU运行。这种调度分2 ... -
linux进程调度发生的时机
2008-09-19 18:03 4131所谓调度时机就是:什么时候会发生进程调度。在linux中,进程 ... -
SSH远程启动服务的问题
2008-09-18 12:32 4719SSH是我们最长用的远程连接linux服务器的工具了,安全 ... -
时钟中断
2008-09-17 16:57 3370时钟中断:是指在计算 ... -
wait4的实现
2008-09-17 15:38 3010不贴实现的代码了,很 ... -
wait4的使用
2008-09-17 10:20 10921wait4会挂起当前进程,等待指定的子进程状态改变,并且会返回 ...
相关推荐
Windows提供了多种线程同步的机制,包括临界区(Critical Sections)、内核事件(Kernel Events)、互斥量(Mutexes)和信号量(Semaphores)。下面将详细介绍这四种同步方式,以及它们在实现线程互斥管理中的不同...
为此,程序员们利用了一系列的技术来管理这种访问,其中包括临界区(CriticalSection)、互斥量(Mutex)以及信号量(Semaphore)。下面将详细介绍这些概念及其在实际开发中的应用。 #### 一、临界区(Critical ...
哈工大软件学院的操作系统实验4聚焦于信号量的实现与应用,旨在让学生深入理解并实践这一关键概念。 信号量是一种抽象的数据类型,由P(wait)和V(signal)操作组成,用于解决进程间的互斥和同步问题。在P操作中,...
临界区适用于同一进程内的线程同步,互斥量支持跨进程同步,而信号量则更适用于控制多个线程对资源的访问次数。根据具体的应用场景选择合适的同步机制,可以有效避免竞态条件的发生,提高程序的稳定性和可靠性。
操作系统课程设计演示信号量.临界区.多进程管理操作系统课程设计演示信号量.临界区.多进程管理操作系统课程设计演示信号量.临界区.多进程管理操作系统课程设计演示信号量.临界区.多进程管理操作系统课程设计演示信号...
本节主要讨论了哈工大操作系统课程第17讲中关于信号量和临界区保护的内容。 首先,当多个进程共同修改共享的信号量时,可能会出现竞态条件(Race Condition),即由于进程调度的不确定性导致的共享数据错误。为了...
7. **线程同步的其他机制**:除了信号量,还有其他的线程同步手段,如临界区、管程、读写锁、条件变量等。它们各有特点,适用于不同的场景,选择合适的同步机制是解决多线程并发问题的关键。 8. **死锁预防**:信号...
在Windows操作系统中,临界区通过定义CRITICAL_SECTION结构体和使用EnterCriticalSection和LeaveCriticalSection函数来实现。当线程调用EnterCriticalSection进入临界区时,如果该临界区未被其他线程占用,那么该...
总之,这个课程设计旨在让学习者深入理解进程间的并发控制,掌握临界区的概念,以及如何使用Java实现进程的同步和互斥。通过实际编程,学生可以更好地理解这些理论知识,并提升解决实际问题的能力。
它利用一个特殊类型的信号量,每个进程在尝试进入临界区前先尝试获取信号量,若无法获取则进入自旋状态,等待其他进程释放信号量。 Peterson算法是为两个进程设计的,通过两个进程共享的两个变量(想进入临界区的...
本教程将深入探讨多线程相关的知识点,包括各种锁机制、条件变量、半成品的CAS操作、临界区、信号量、事件、互斥锁以及队列。 **多线程**:多线程是操作系统提供的一种并发执行机制,一个进程可以包含多个线程,每...
在C语言中,通常使用系统调用来实现信号量的操作。例如,POSIX标准提供了一套信号量API,包括`sem_init()`、`sem_wait()`、`sem_post()`等函数。 #### 三、信号量的实现 在给定的部分内容中,提供了两个示例程序:...
在多任务操作系统中,为了确保共享资源的正确访问和管理,内核通常采用信号量机制来实现同步。Linux内核中的信号量机制主要用于解决多线程或多进程之间对共享资源的访问冲突问题。在Linux内核中,信号量机制主要包括...
例如,我们可以创建一个二进制信号量,并在任务开始时调用`semTake()`,在结束时调用`semGive()`来保护临界区。 任务同步则涉及任务按照预定顺序执行,通常通过设置初始值为不可用的信号量来实现。任务A在完成其...
临界区、互斥量(mutex)、信号量(semaphore)和事件(event)是四种常见的同步原语,它们用于管理和协调并发执行的线程,确保资源的安全访问和避免竞态条件。以下是对这些概念的详细解释: 1. **临界区(Critical...
Windows提供了多种同步机制,包括临界区(Critical Sections)、内核对象(如事件Event、互斥量Mutex、信号量Semaphore)等,它们各自有不同的特点和使用场景。 ### 临界区(Critical Sections) 临界区是最轻量级...
在UCOSII中,二进制信号量只能处于两种状态:0或1,适合保护临界区或互斥访问;而计数信号量则可以有大于1的数值,可用于多个任务共享同一资源的情况。 1. **二进制信号量**: - 当信号量值为1时,表示资源可用。...
在Java中,这可以通过synchronized关键字来实现,而在操作系统层面,通常使用信号量来完成这一功能。 Linux提供了三个系统调用来管理信号量:semget、semop和semctl。semget用于创建或查找信号量集,semop用于执行...
信号量在操作系统中起着“交通警察”的角色,它通过计数器的形式来保护临界区,避免发生数据竞争和死锁。在Linux内核中,信号量分为两种类型:互斥信号量(mutex)和普通信号量(semaphore)。互斥信号量主要用于...
在Python中,可以使用`threading.Semaphore`类来实现信号量。例如,创建一个计数信号量: ```python import threading semaphore = threading.Semaphore(3) # 创建一个值为3的信号量 def worker(): semaphore....