本文主要是介绍Linux进程与线程之五,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
每日一结
一 共享内存 :内核空间预留出来的一块内存,用于进程间通信
(1)int shmget(key_t key, size_t size, int shmflg);
功能:获取共享内存段的ID
参数:
@key IPC_PRIVATE 或 ftok()
@size 申请的共享内存段大小 [4k的倍数]
@shmflg IPC_CREAT | 0666 或 IPC_CREAT | IPC_EXCL
返回值:
成功返回ID,失败返回-1
(2)void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:映射共享内存到用户空间
参数:
@shmid 共享内存段ID
@shmaddr NULL:系统自动完成映射
@shmflg SHM_RDONLY:只读 0:读写
返回值:
成功返回映射后的地址,失败返回(void *)-1
练习:A,B通过共享内存通信
B如何知道A已经写了数据?
flag
----------------------------------------------
0 | 内容
-----------------------------------------------
(3)int shmdt(const void *shmaddr);
功能:撤销映射
参数:
@shmaddr 共享内存映射的地址
(4)int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:根据命令控制共享内存
参数:
@shmid 共享内存段的ID
@cmd IPC_STAT[获取属性],IPC_SET[设置属性],IPC_RMID[删除IPC对象]
@buf 保存属性
返回值:
成功返回0,失败返回 -1
-----------------------------------------------------------
注意:当我们调用shmctl删除共享内存的时候,并不会立即删除。只有当共享内存映射次数为0,才会删除共享内存对象
代码示例如下:
关于Linux环境进程间通信的参考资料:
共享内存:
上:http://www.ibm.com/developerworks/cn/linux/l-ipc/part5/index1.html
下:http://www.ibm.com/developerworks/cn/linux/l-ipc/part5/index2.html
-----------------------------------------------------------
二 信号灯集
POSIX 线程中的同步用的是无名信号量
进程间的同步使用的是IPC 对象[信号灯集]
信号灯集:信号灯集合,每一个信号灯都可以用来表示一类资源,其值表示资源的个数
(1)创建信号灯集
int semget(key_t key, int nsems, int semflg);
参数:
@key IPC_PRIVATE , ftok()
@nsems 信号灯集中信号灯的个数
@semflg IPC_CREAT | 0666,IPC_CREAT | IPC_EXCL
返回值:
成功返回ID,失败返回-1
(2)初始化信号灯集中信号灯的值
int semctl(int semid, int semnum, int cmd, ...);
参数:
@semid 信号灯集的ID
@semnum 信号灯的编号[编号从0开始]
@cmd SETVAL[设置信号灯的值] ,GETVAL(获取信号灯的值),IPC_RMID[删除信号灯集]
返回值:
成功返回0,失败返回-1
思考:将信号灯集中的1号信号灯初始化为1?
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) */
};
void init_sem_value(int sem_id,int sem_num,int value)
{
union semun sem_val;
sem_val.val = value;
if(semctl(sem_id,sem_num,SETVAL,sem_val) < 0)
{
...
}
return ;
}
(3)PV操作
int semop(int semid, struct sembuf *sops, unsigned nsops);
功能:完成PV操作
参数:
@semid 信号灯集的ID
@sops 操作方式结构体首地址
@nsops 操作信号灯的个数
返回值:
成功返回0,失败返回-1
struct sembuf
{
unsigned short sem_num; /* semaphore number */
short sem_op; /* semaphore operation */
short sem_flg; /* operation flags */
};
sem_op :
<1>0 等待信号灯的值变成0
<2>1 释放资源,V操作
<3>-1 申请资源,P操作
sem_flg:
0 : 阻塞方式
IPC_NOWAIT : 非阻塞方式调用
SEM_UNDO : 进程结束的时候,它申请的资源自动释放
-----------------------------------------------------------------
void P(int sem_id,int sem_num)
{
struct sembuf sem;
sem.sem_num = sem_num;
sem.sem_op = -1;
sem.sem_flg = 0;
if(semop(sem_id,&sem,1) < 0)
{
....
}
}
void V(int sem_id,int sem_num)
{
struct sembuf sem;
sem.sem_num = sem_num;
sem.sem_op = 1;
sem.sem_flg = 0;
if(semop(sem_id,&sem,1) < 0)
{
....
}
}
关于Linux环境进程间通信的参考资料
信号灯:
http://www.ibm.com/developerworks/cn/linux/l-ipc/part4/
练习:
A,B通过信号灯集同步对共享内存操作
让创建信号灯集的进程,初始化信号灯的值 ,如果信号灯集已经存在则不初始化
sem_id = semget(key,2,IPC_CREAT | IPC_EXCL | 0666);
if(sem_id < 0)
{
sem_id = semget(key,2,IPC_CREAT | 0666);
}
参考代码如下:
sem.c



shm_write.c


shm_read.c


注意:shm_read.c 和 shm_write.c 都需要单独和sem.c一起编译
亦即:gcc shm_read.c sem.c -o shm_read
gcc shm_write.c sem.c -o shm_write
关注微信公众号获取更多资讯
这篇关于Linux进程与线程之五的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!