进程线程通信方式

一、进程通信

1.管道

(1)无名管道

所用函数:

int pipe(int pipefd[2]);

返回值:成功0,失败-1
参数:数组
代码示例:

int p[2];

	if(-1 == pipe(p))
	{
		perror("pipe");
		exit(-1);
	}

在进程中具体使用方式如下:

else if(0 == pid) //子进程
	{
		close(p[1]);//关闭写
		char buf[20];
		read(p[0], buf, sizeof(buf));
		puts(buf);
		exit(0);
	}
	else //父进程
	{
		close(p[0]);//关闭读
		char buf[20];
		gets(buf);
		write(p[1], buf, sizeof(buf));
		exit(0);
		wait(NULL);
	}

(2)有名管道

半双工 命令;mkfifo
所用函数:

int mkfifo(const char * pathname,mode_t mode);

返回值:成功0 失败-1;
参数:pathname 管道权限
​ mode 文件权限
代码示例:
write.c:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
	if(-1 == mkfifo("fifo", 0666))
	{
		perror("mkfifo");
		exit(-1);
	}


	int fd = open("fifo", O_WRONLY);
	if(-1 == fd)
	{
		perror("open");
		exit(-1);
	}

	char buf[20];

	while(1)
	{
		gets(buf);
		write(fd, buf, sizeof(buf));


	}

}

read.c:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
	int fd = open("fifo", O_RDONLY);
	if(-1 == fd)
	{
		perror("open");
	}

	char buf[20];

	while(1)
	{
		read(fd, buf, sizeof(buf));

		puts(buf);

	}

}

编写使用时记得把fifo文件删除

2.信号

所用函数:

int raise(int sig);//给自己发送信号

返回值:成功0 失败-1;
参数:sig :信号

int kill(pid_t pid, int sig);//给别人发送信号

返回值:成功0 失败-1;
参数:

  • pid 传过来的pid
  • ​sig:信号
unsigned int alarm(unsigned int seconds);

返回值:如果第一次使用,返回0,如果不是第一次,返回上一次计数剩余时间
参数:seconds:秒数

typedef void (*sighandler_t)(int);
(void*)-1 == sighandler_t signal(int signum, sighandler_t handler); //处理捕获函数

返回值:失败NULL,成功处理函数首地址
参数:

  • signum:处理信号
  • handler:处理函数(SIG_IGN:忽略 SIG_DFL:缺省)

3.IPC

(1)共享内存

1.创建共享内存
所用函数:

int shmget(key_t key, size_t size, int shmflg);

返回值:成功返回id 失败-1
参数:

  • key:key值
  • size:共享内存大小
  • shmflg:权限
 key_t ftok(const char *pathname, int proj_id);

返回值:成功返回key值,失败返回-1
参数:

  • pathname:文件路径
  • proj_id:通常会给一个字符
    代码示例:
key_t key = ftok("1.txt", 'A');
	if(-1 == key)
	{
		perror("ftok");
		exit(-1);

	}
	printf("key=%X\n", key);
	//打开/创建一个ipc对象获取id
	int shmid = shmget(key, 1024, IPC_CREAT);
	if(-1 == shmid)
	{
		perror("shmget");
		exit(-1);
	}

2.映射
所用函数:

void *shmat(int shmid, const void *shmaddr, int shmflg);

返回值:成功返回映射后的用户地址,失败返回-1
参数:

  • shmid: 共享内存id
  • shmaddr:映射的位置,一般为NULL,自动分配
  • shmflg:打开方式,通常用SHM_RDONLY,默认0

注意!!!运行时需要加sudo
代码示例:

void*addr = NULL;
	addr = shmat(shmid, NULL, 0);
	if((void*)-1 == addr)
	{
		perror("shmat");
		exit(-1);
	}

3.取消映射
所用函数:

int shmdt(const void *shmaddr);

返回值:成功0,错误-1
参数: 映射的首地址
代码示例:

if(-1 == shmdt(addr))
		{
			perror("shmdt");
			exit(-1);
		}

4.删除共享内存
所用函数:

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

返回值:成功0,错误-1
参数:

  • shmid :共享内存id
  • cmd :IPC_SET IPC_STAT //需要传递第三个参数
    IPC_RMID 删除,不用第三个参数

代码示例:

	if(-1 == shmctl(shmid, IPC_RMID, NULL))
		{
			perror("shmctl");
			exit(-1);
		}

(2)信号灯集

1.创建信号灯集
所用函数:

 int semget(key_t key, int nsems, int semflg);

返回值:成功返回id 失败-1
参数:

  • key:ftok的值
  • nsems::灯集个数
  • semflags:权限 IPC_CREAT|0600

代码示例:

int sem_id = semget(key, 2, IPC_CREAT|0600);
	if(-1 == sem_id)
	{
		perror("sem_get");
		return -1;
	}

2.给信号灯初值
所用函数:

int semctl(int semid, int semnum, int cmd, union buf);

返回值:失败返回-1
参数:

  • semid:信号灯集的id
  • semnum:信号灯编号
  • cmd:执行操作
  • buf:相关共用体

代码示例:

union semun sun;
	sun.val = 0;
	if(-1 == semctl(sem_id, R, SETVAL, sun))
	{
		perror("setval");
		return -1;
	}


	sun.val = 1;
	if(-1 == semctl(sem_id, W, SETVAL, sun))
	{
		perror("setval");
		return -1;
	}

3.生产/消费
所用函数:

int semop(int semid, struct sembuf *sops, size_t nsops);

返回值:成功0,错误-1
参数:

  • semid:信号灯id
  • sembuf:操作的结构体首地址
  • nsops:操作的信号灯个数

代码示例:

//消费
int P(int sem_id, int semnum)
{
	struct sembuf sem_val;
	sem_val.sem_num = semnum;   //第几个信号灯
	sem_val.sem_op = -1;        //消费
	sem_val.sem_flg = 0;               
	
	if(-1 == semop(sem_id, &sem_val, 1))
	{
		perror("semop");
		return -1;
	}
	return 0;
}
//生产
int V(int sem_id, int semnum)
{

	struct sembuf sem_val;
	sem_val.sem_num = semnum; //第几个信号灯
	sem_val.sem_op = 1;	  //生产
	sem_val.sem_flg = 0;

	if(-1 == semop(sem_id, &sem_val, 1))
	{
		perror("semop");
		return -1;
	}
	return 0;

}

(3)消息队列

1.创建消息队列
所用函数:

int msgget(key_t key, int msgflg);

返回值:消息队列id,失败-1
参数:

  • key:key值
  • msgflg:权限
    代码示例:
int msgid = msgget(key, IPC_CREAT|0600);
	if(-1 == msgid)
	{
		perror("msgget");
		exit(-1);
	}

2.发送消息/接收消息
所用函数:
第一种:

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

返回值:成功0,失败-1
参数:

  • msqid:消息队列id
  • msgp:消息 结构体首地址
  • msgsz:消息大小(不包含type)
  • msgflg:权限,默认0

代码示例:

struct msgbuf buf;
		buf.type = 100;
		strcpy(buf.buf, "hello");

		if(-1 == msgsnd(msgid, &buf, sizeof(buf.buf), 0))
		{
			perror("msgsdn");
			exit(-1);
		}

第二种:

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);

返回值:成功0,失败-1
参数:

  • msqid:消息队列id
  • msgp:消息 结构体首地址
  • msgsz:消息大小(不包含type)
  • msgtyp:消息的编号
  • msgflg:权限,默认0

代码示例:

struct msgbuf buf;
		int ret = msgrcv(msgid, &buf, sizeof(buf.buf), 100, 0);
		if(-1 == ret)
		{
			perror("msgrcv");
			exit(-1);
		}

二、线程通信

1.同步

  按照一定的顺序去完成某一件事情

信号量

1.创建信号量,并初始化
所用函数:

int sem_init(sem_t *sem, int pshared, unsigned int value);

返回值:成功0,失败非0
参数:

  • sem:信号量
  • pshared:0共享
  • value:初值
    代码示例:
	if(0 != sem_init(&read, 0, 0))
	{
		perror("seminnit");
		exit(-1);
	}
	if(0 != sem_init(&write, 0, 1))
	{
		perror("seminnit");
		exit(-1);
	}

2.消费
所用函数:

int sem_wait(sem_t *sem);

返回值:成功0,失败非0
参数:sem:信号量
3.生产
所用函数:

int sem_post(sem_t *sem);

返回值:成功0,失败非0
参数:sem:信号量
代码示例:

while(1)
	{
		sem_wait(&read);
		puts(buf);
		sem_post(&write);
	}

2.互斥

  某一线程正在使用某个资源时,那么其他线程就不能使用该线程

互斥锁

1.创建锁,并且初始化
所用函数

int  pthread_mutex_init(pthread_mutex_t  *mutex,  const  pthread_mutex‐
       attr_t *mutexattr);

返回值:成功0;失败非0
参数

  • mutex:锁
  • mutexattr:属性 默认属性NULL
    代码示例:
pthread_mutex_t mutex;
if(0 != pthread_mutex_init(&mutex, NULL))
  {
  	perror("mutex_init");
  	pthread_exit(NULL);
  }

2.上锁
所用函数

int pthread_mutex_lock(pthread_mutex_t *mutex);

返回值:成功0,失败非0
参数:mutex :锁

3.解锁
所用函数

int pthread_mutex_unlock(pthread_mutex_t *mutex);

返回值:成功0,失败非0
参数:mutex :锁
代码示例:

while(1)
	{
		pthread_mutex_lock(&mutex);
		if(a == b)
		{
			printf("hello a=%d b=%d\n", a, b);
		}
		pthread_mutex_unlock(&mutex);
	}

4.摧毁锁
所用函数

int pthread_mutex_destroy(pthread_mutex_t *mutex);

返回值:成功0失败非0
参数:mutex:锁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值