可以作用于linux下任意两个进程,机制就是使用同一片共享的内存区域,使得两个任意的进程访问这个区域,实现数据的交换。
key = ftok(".",10);
功能:allocates a shared memory segment -> 申请共享内存块
使用格式:
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
key:key值
size:共享内存的总字节数 PAGE_SIZE的倍数 #define PAGE_SIZE 1024
shmflg: IPC_CREAT|0666 -> 不存在则创建
IPC_EXCL -> 存在则报错
返回值:
成功:共享内存的ID
失败:-1
使用格式:
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
shmid:共享内存的ID
shmaddr: NULL -> 系统自动分配 99%
不为NULL -> 用户自己分配 1%
shmflg: 普通属性代表内存空间可读可写,填0
返回值:
成功:该内存空间的起始地址
失败:(void *)-1
使用格式:
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);
shmaddr: 该内存空间的起始地址
返回值:
成功:0
失败:-1
使用格式:
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
shmid:共享内存的ID
cmd:IPC_RMID -> 删除
buf:NULL
返回值:
成功:0
失败:-1
#include "head.h"
int main()
{
//1. 申请key值
key_t key = ftok(".",10);
//2. 根据key值申请共享内存ID号
int shmid = shmget(key,2048,IPC_CREAT|0666);
//3. 根据ID号申请共享内存的起始地址
char *p = (char *)shmat(shmid,NULL,0);
//4. 不断读取共享内存的数据
while(1)
{
printf("from shm:%s",p);
usleep(500000);
if(strncmp(p,"quit",4) == 0)
{
break;
}
}
shmdt(p);
shmctl(shmid,IPC_RMID,NULL);
return 0;
}
#include "head.h"
int main()
{
//1. 申请key值
key_t key = ftok(".",10);
//2. 根据key值申请共享内存ID号
int shmid = shmget(key,2048,IPC_CREAT|0666);
//3. 根据ID号申请共享内存的起始地址
char *p = (char *)shmat(shmid,NULL,0);
//4. 往共享内存中写入数据
bzero(p,2048);
while(1)
{
fgets(p,2048,stdin);
if(strncmp(p,"quit",4) == 0)
{
break;
}
}
return 0;
}
信号量虽然属于IPC对象,但是它不属于进程之间的通信,它只是用于处理同步互斥。
key = ftok(".",10);
使用格式:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
key:key值
nsems:信号量的元素个数。 例如: 空间和数据 -> 2
semflg: IPC_CREAT|0666 -> 不存在则创建
IPC_EXCL -> 存在则报错
返回值:
成功:信号量的ID
失败:-1
使用格式:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, unsigned nsops);
semid:信号量的ID
sops:进行P/V操作的结构体
struct sembuf{
unsigned short sem_num; 需要操作的成员的下标: 空间 -> 0 数据 ->1
short sem_op; P操作/V操作 P操作 ->-1 V操作 ->1
short sem_flg; 普通属性,填0
}
nsops:信号量操作结构体个数 -> 1
返回值:
成功:0
失败:-1
使用格式:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semctl(int semid, int semnum, int cmd, ...);
semid:信号量的ID
semnum:需要操作的成员的下标: 空间 -> 0 数据 ->1
cmd: SETVAL -> 用于设置信号量元素的起始值
IPC_RMID -> 删除信号量
...:空间/数据的起始值
例子: 初始化空间:0 数据:1
semctl(semid,0,SETVAL,0);
semctl(semid,1,SETVAL,1);
进程: ./xxx -> 开启一个新的进程 -> 是系统中最小的资源分配单位。
int main()
{
/* 进程开始 */
....
/* 进程结束 */
return 0;
}
线程: 是一个进程内部的资源,是系统中最小调度单位。
功能: create a new thread -> 创建子线程。
使用格式:
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
thread:存放线程TID号的变量的地址
pthread_t其实是线程TID号的数据类型
attr:属性变量 -> 不为NULL,自定义属性
-> 为NULL,普通属性
start_routine: 线程执行例程函数,类型必须是: void *fun(void *arg)
arg:传递给例程函数的参数
返回值:
成功:0
失败:非0错误码
例子: gcc test.c -o test -lpthread
#include "head.h"
void *fun(void *arg) //arg = &a
{
int a = *(int *)arg;
printf("a = %d\n",a);
int i;
for(i=0;i<10;i++)
{
printf("child thread:%d\n",i);
sleep(1);
}
}
int main(int argc,char *argv[])
{
/* 暂时来讲,都只是一个单线程 */
printf("helloworld!\n");
/* 创建一个新的子线程 */
pthread_t tid;
int ret,i;
int a = 10;
ret = pthread_create(&tid,NULL,fun,(void *)&a);
printf("ret = %d\n",ret);
printf("tid = %d\n",(int)tid);
for(i=0;i<5;i++)
{
printf("main thread:%d\n",i);
sleep(1);
}
return 0;
}
创建线程与调用函数接口有什么不同? -> 见"调用函数与创建线程的区别.jpg"
功能: join with a terminated thread -> 接合一个结束的子线程
使用格式:
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
thread:需要接合的线程的TID号
retval:存储子线程退出值的指针 如果填NULL,不关心子线程的退出。
返回值:
成功:0
失败:错误码
#include "head.h"
void *fun(void *arg) //arg = &a
{
int a = *(int *)arg;
printf("a = %d\n",a);
int i;
for(i=0;i<10;i++)
{
printf("child thread:%d\n",i);
sleep(1);
}
}
int main(int argc,char *argv[])
{
/* 暂时来讲,都只是一个单线程 */
printf("helloworld!\n");
/* 创建一个新的子线程 */
pthread_t tid;
int ret,i;
int a = 10;
//fun((void *)&a);
ret = pthread_create(&tid,NULL,fun,(void *)&a);
printf("ret = %d\n",ret);
printf("tid = %d\n",(int)tid);
for(i=0;i<5;i++)
{
printf("main thread:%d\n",i);
sleep(1);
}
// 接合子线程
ret = pthread_join(tid,NULL);
printf("ret = %d\n",ret);
return 0;
}
该函数的功能:
1)terminate calling thread -> 提前结束线程
2)为了返回一个退出值给主线程。
使用格式:
#include <pthread.h>
void pthread_exit(void *retval);
retval:子线程的退出值。 -> 退出值不能是局部变量。
返回值:无。
例子: 主线程主动结合子线程,并且关心子线程退出状态。
#include "head.h"
int exit_state = 5;
void *fun(void *arg) //arg = &a
{
int a = *(int *)arg;
printf("a = %d\n",a);
int i;
for(i=0;i<10;i++)
{
printf("child thread:%d\n",i);
sleep(1);
}
pthread_exit((void *)&exit_state);
}
int main(int argc,char *argv[])
{
/* 暂时来讲,都只是一个单线程 */
printf("helloworld!\n");
/* 创建一个新的子线程 */
pthread_t tid;
int ret,i;
int a = 10;
void *p = NULL;
//fun((void *)&a);
ret = pthread_create(&tid,NULL,fun,(void *)&a);
printf("ret = %d\n",ret);
printf("tid = %d\n",(int)tid);
for(i=0;i<5;i++)
{
printf("main thread:%d\n",i);
sleep(1);
}
// 接合子线程
ret = pthread_join(tid,&p); // p = (void *)&exit_state
printf("ret = %d\n",ret);
printf("exit_state = %d\n",*(int *)p);
return 0;
}
原文:https://www.cnblogs.com/zjlbk/p/11347552.html