信号量、进程间的通信

一、信号量

信号量(semaphore)是操作系统用来解决并发中的互斥和同步问题的一种方法。

信号量 (个数) --- 反映的是资源的数量

信号量的分类:信号无名量 ==》线程间通信

                         有名信号量 ==》进程间通信

1.信号量的定义 (为全局变量)

sem_t  sem

sem_t:信号量的类型,sem:信号量的变量

例如: sem_t sem_w;,sem_t sem_r;


sem_t sem_1;
sem_t sem_2;

2.信号量的初始化

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

功能:将已经定义好的信号量赋值。

参数:sem 要初始化的信号量,pshared = 0 ;表示线程间使用信号量,!=0 ;表示进程间使用信号量,value 信号量的初始值,一般无名信号量都是二值信号量(0 1) ,0 表示红灯,进程暂停阻塞,1 表示绿灯,进程可以通过执行

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

sem_init(&sem_1,0,1);
sem_init(&sem_2,0,0);

3.信号量的PV操作

sem_wait()/ sem_post()

 P ===》申请资源===》申请一个二值信号量int sem_wait(sem_t *sem); 
功能:判断当前sem信号量是否有资源可用。如果sem有资源(==1),则申请该资源,程序继续运行如果sem没有资源(==0),则线程阻塞等待,一旦有资源则自动申请资源并继续运行程序。

注意:sem 申请资源后会自动执行 sem = sem - 1;

参数:sem 要判断的信号量资源

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

 V ===》释放资源===》释放一个二值信号量,nt sem_post(sem_t *sem); 

功能:函数可以将指定的sem信号量资源释放并默认执行,sem = sem+1; 线程在该函数上不会阻塞。

参数:sem 要释放资源的信号量

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

void *doWin2(void *arg)
{
	int i = 0;
	while (1)
	{
		sem_wait(&sem_2);
		if (ticket <= 0)
		{
			sem_post(&sem_1);
			break;
		}
		ticket--; //1 => 0
		printf("win2 sell ticket = %d\n",100-ticket); //100 
		sem_post(&sem_1);
	}

	pthread_exit(NULL);
}

4.信号量的销毁

 int sem_destroy(sem_t *sem);

功能:使用完毕将指定的信号量销毁

参数:sem要销毁的信号量

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

sem_destroy(&sem_1);
sem_destroy(&sem_2);

二、进程间的通信 

进程创建好之后,父子进程的空间 相互独立 。

1.通信的方式

1、古老的通信方式

管道:无名管道    (1),有名管道    (2)

信号  (3)

2、IPC对象通信 system v    BSD     suse fedora   kernel.org

                          消息队列  (4)

                           共享内存(*) //最高效                (5)

                          信号量集() //信号量                 (6)

3、socket通信

网络通信        (7)

2.管道:  无名管道 

1.int pipe(int pipefd[2]);  

功能:创建一个管道 

参数:pipefd //用来获取 管道的两端 ,读端pipefd[0] ,写端pipefd[1]

返回值:成功 0,失败 -1 && errno  

#include 
#include 
#include 
int main(int argc, const char *argv[])
{
	int fd[2];

	if (pipe(fd) < 0)
	{
		perror("pipe fail");
		return -1;
	}
	char buf[] = "hello pipe\n";
	write(fd[1],buf,strlen(buf));
    char bufr[100] = {0};
	read(fd[0],bufr,sizeof(bufr));
	printf("bufr = %s\n",bufr);
	return 0;
}

2.管道的特点

管道大小 65536字节   64k 

管道操作特点 ,数据读走之后,认为就没了 

3.管道的读写规则

1.读端存在,写管道

      管道空:可以写数据

      管道满:会造成-->写阻塞 

2.读端不存在,写管道

      系统会给进程发一个信号SIGPIPE(管道破裂)

3.写端存在,读管道

      管道空,读不到数据,

      这时会造成读操作阻塞

4.写端不存在,读管道 

     如果管道中有数据,则读取这些数据!

     如果没有数据,读操作不阻塞,立即返回!

你可能感兴趣的:(学习)