linux C学习笔记05--信号量与共享内存(进程同步)
花了半天时间把信号量与共享内存整合到了一起,先来看信号量代码,semaphore.c 当中sem_P()和sem_V()函数分别为信号量等待和信号量释放。
两个进程同时访问共享内存,为了避免发生同时读写产生不必要的错误,加入了信号量进行同步。对使用共享内存的区域加上互斥锁,同时只有一个进程能访问共享内存,时其他进程必须等待信号量资源释放后才能继续访问
/*************************************************************************
> File Name: semaphore.c
> Author: hailin.ma
> Mail: mhl2018@126.com
> Created Time: Thu 28 May 2015 09:29:35 AM CST
************************************************************************/ #include <stdio.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/sem.h> #define SEM_KEY 27 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 create_semaphore()
{
int semid;
union semun sembuf; sembuf.val = ; if((semid = semget(SEM_KEY,, IPC_CREAT|IPC_EXCL|)) == -)
{
if(errno == EEXIST)
{
semid = semget(SEM_KEY,,);
if(semid == -)
{
perror("semget");
return -;
}
else
{
if (semctl(semid,,SETVAL,sembuf) == -)
{
perror("semctl");
return -;
}
else
{
return semid;
}
} }
else
{
perror("semget");
return -;
}
}
else
{
if (semctl(semid,,SETVAL,sembuf) == -)
{
perror("semctl");
return -;
}
} return semid;
} int delete_semaphore(int semid)
{
union semun sembuf;
if(semctl(semid,,IPC_RMID,sembuf) == -)
{
perror("delete_semaphore");
return -;
}
} int sem_P(int semid)
{
struct sembuf sbuf;
sbuf.sem_num = ;
sbuf.sem_op = -;
sbuf.sem_flg = SEM_UNDO; if(semop(semid,&sbuf,) == -)
{
perror("sem_P");
return -;
} return ;
} int sem_V(int semid)
{
struct sembuf sbuf;
sbuf.sem_num = ;
sbuf.sem_op = ;
sbuf.sem_flg = SEM_UNDO; if(semop(semid,&sbuf,) == -)
{
perror("sem_P");
return -;
}
}
下面是共享内存代码:
/*************************************************************************
> File Name: share_memory.c
> Author: hailin.ma
> Mail: mhl2018@126.com
> Created Time: Wed 27 May 2015 11:19:26 PM CST
************************************************************************/ #include<stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <errno.h> #define SHARE_MEM_KEY 26
#define MEMORY_SIZE 1000 int create_shm(char **shmptr)
{
int shmid; //if((shmid = shmget(IPC_PRIVATE,200,IPC_CREAT|IPC_EXCL|0666)) == -1)
if((shmid = shmget(SHARE_MEM_KEY,MEMORY_SIZE,IPC_CREAT|IPC_EXCL|)) == -)
{
if(errno == EEXIST)
{
shmid = shmget(SHARE_MEM_KEY,,);
if(shmid == -)
{
perror("shmget");
return -;
}
else
{
if((*shmptr = shmat(shmid,,)) == (void*)-)
{
perror("shmat");
return -;
}
else
{
return shmid;
}
}
}
else
{
perror("shmget");
return -;
}
} if((*shmptr = shmat(shmid,,)) == (void*)-)
{
perror("shmat");
return -;
} return shmid;
} int delete_shm(int shmid,char *shmptr)
{
shmdt(shmptr);
if(shmctl(shmid,IPC_RMID,NULL) == -)
{
perror("delete_shm");
return -;
} return ;
}
main函数代码:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h> extern int create_shm(char **shmptr);
extern int create_semaphore();
extern int delete_semaphore();
extern int sem_P(int semid);
extern int sem_V(int semid);
extern int delete_shm(int shmid,char *shmptr); int main(int argc,char* argv[])
{
int shmid;
char *shmptr;
int semid; if((shmid =create_shm(&shmptr)) == -)
{
printf("create_shm error \n");
return -;
}
if(argc > )
{
semid = *(int*)shmptr; //get semid from share memory //this is client
while()
{
printf("input str to share memory:");
sem_P(semid);
gets(shmptr);
sem_V(semid);
if(shmptr[] == 'q') //quit
{
shmdt(shmptr); //disconnect to the share memory but will not dellect the memery
break;
}
}
}
else
{
if((semid = create_semaphore()) == -)
{
perror("main create_semaphore");
delete_shm(shmid,shmptr);
return -;
}
*(int*)shmptr = semid;
printf("share memory is: %d \n",*(int*)shmptr); //this is server
while()
{
sleep();
sem_P(semid);
printf("share memory is: %s \n",shmptr);
sem_V(semid);
if(shmptr[] == 'q')
{
delete_shm(shmid,shmptr);
delete_semaphore(semid);
break;
}
}
} printf("into sleeping\n");
sleep();
printf("out sleeping\n"); return ;
}
运行效果图:
linux C学习笔记05--信号量与共享内存(进程同步)的更多相关文章
- linux io 学习笔记(03)---共享内存,信号灯,消息队列
system V IPC 1)消息队列 2)共享内存 3)信号灯(信号量集) 1.消息队列. ipcs -q 查看系统中使用消息队列的情况 ipcrm -q +msqid 删除消息队列 消息队列工作原 ...
- Linux系统学习笔记:文件I/O
Linux支持C语言中的标准I/O函数,同时它还提供了一套SUS标准的I/O库函数.和标准I/O不同,UNIX的I/O函数是不带缓冲的,即每个读写都调用内核中的一个系统调用.本篇总结UNIX的I/O并 ...
- Linux内核学习笔记-2.进程管理
原创文章,转载请注明:Linux内核学习笔记-2.进程管理) By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...
- Linux内核学习笔记-1.简介和入门
原创文章,转载请注明:Linux内核学习笔记-1.简介和入门 By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...
- Linux内核学习笔记二——进程
Linux内核学习笔记二——进程 一 进程与线程 进程就是处于执行期的程序,包含了独立地址空间,多个执行线程等资源. 线程是进程中活动的对象,每个线程都拥有独立的程序计数器.进程栈和一组进程寄存器 ...
- linux kernel学习笔记-5内存管理_转
void * kmalloc(size_t size, gfp_t gfp_mask); kmalloc()第一个参数是要分配的块的大小,第一个参数为分配标志,用于控制kmalloc()的行为. km ...
- Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存
Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存 参考:<linux编程从入门到精通>,<Linux C程序设计大全>,<unix环境高级编程> ...
- 尚硅谷韩顺平Linux教程学习笔记
目录 尚硅谷韩顺平Linux教程学习笔记 写在前面 虚拟机 Linux目录结构 远程登录Linux系统 vi和vim编辑器 关机.重启和用户登录注销 用户管理 实用指令 组管理和权限管理 定时任务调度 ...
- linux 驱动学习笔记01--Linux 内核的编译
由于用的学习材料是<linux设备驱动开发详解(第二版)>,所以linux驱动学习笔记大部分文字描述来自于这本书,学习笔记系列用于自己学习理解的一种查阅和复习方式. #make confi ...
随机推荐
- C语言数组初始化
例如: int a[15] = {0}; 第一种,编译器会把第一个初始化值赋给数组的第一个元素,然后用0赋给其余的元素.如果没有给出初始值,编译器不会去做初始化工作.这样简洁的方式让代码更加高效. 还 ...
- PAT (Basic Level) Practise:1028. 人口普查
[题目链接] 某城镇进行人口普查,得到了全体居民的生日.现请你写个程序,找出镇上最年长和最年轻的人. 这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过200岁的老人,而今天是 ...
- python数据结构与算法——二叉树结构与遍历方法
先序遍历,中序遍历,后序遍历 ,区别在于三条核心语句的位置 层序遍历 采用队列的遍历操作第一次访问根,在访问根的左孩子,接着访问根的有孩子,然后下一层 自左向右一一访问同层的结点 # 先序遍历 # ...
- Ubuntu下安装配置JDK 7
第一步:下载jdk-7-linux-i586.tar.gz wget -c http://download.oracle.com/otn-pub/java/jdk/7/jdk-7-linux-i586 ...
- UVa 439骑士的移动(BFS)
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- RPM卸载软件包
如何卸载rpm包 首先:通过 rpm -q <关键字> 可以查询到rpm包的名字 然后:调用 rpm -e <包的名字> 删除特定rpm包 如果遇到依赖,无法删除,使用 rp ...
- [JSOI2008][BZOJ1012] 最大数(动态开点线段树)
题目描述 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值. 限制:L不超过当前数列的长度. 2. 插入操作 ...
- C中变量名通过宏定义转换成char*类型字符串
#include <iostream> #include <stdlib.h> #define name_to_str(name)(#name) int main() { in ...
- 深入C#中get与set的详解(转)
转自:http://www.jb51.net/article/37960.htm 释一:属性的访问器包含与获取(读取或计算)或设置(写)属性有关的可执行语句.访问器声明可以包含 get 访问器或 se ...
- world machine, 输出lightmap
一,输出黑白lightmap: 二,输出彩色lightmap: 需要注意的是:当输出黑白lightmap时,输出设备要用Height Output:当输出彩色lightmap时,输出设备要用Bitma ...