1.线程任务同步:
1.信号量:
是一种资源,可以被申请、释放、初始化
释放:让资源数+1,不会阻塞
申请:让资源数-1,如果当前资源数为0,申请资源时会阻塞等待,直到资源不为0,才能继续向下执行
Linux内核:
PV操作, P申请 V释放
2.函数接口:
1.sem_init
int sem_init(sem_t *sem, int pshared, unsigned int value);
功能:
信号量的初始化
参数:
sem:信号量空间首地址
pshared:
0 线程间使用
非0 进程间使用
value:
信号量初始化的值
返回值:
成功返回0
失败返回-1
2.sem_destroy
int sem_destroy(sem_t *sem);
功能:
信号量的销毁
3.sem_wait
int sem_wait(sem_t *sem);
功能:
信号量资源申请
4.sem_post
int sem_post(sem_t *sem);
功能:
信号量资源释放
练习:
创建3个线程任务,任务一循环打印 "A",任务二循环打印"B",
任务三循环打印"C",要求打印出来的顺序总是先
"A" -> "B" -> "C"
#include
#include
#include
#include
sem_t sem_a;
sem_t sem_b;
sem_t sem_c;
void *WriteA(void *arg)
{
while(1)
{
sem_wait(&sem_a);
sleep(3);
printf("A\n");
sem_post(&sem_b);
}
return NULL;
}
void *WriteB(void *arg)
{
while(1)
{
sem_wait(&sem_b);
sleep(3);
printf("B\n");
sem_post(&sem_c);
}
return NULL;
}
void *WriteC(void *arg)
{
while(1)
{
sem_wait(&sem_c);
sleep(3);
printf("C\n");
sem_post(&sem_a);
}
return NULL;
}
int main(void)
{
pthread_t tid1;
pthread_t tid2;
pthread_t tid3;
sem_init(&sem_a, 0, 1);
sem_init(&sem_b, 0, 0);
sem_init(&sem_c, 0, 0);
pthread_create(&tid1, NULL, WriteA, NULL);
pthread_create(&tid2, NULL, WriteB, NULL);
pthread_create(&tid3, NULL, WriteC, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_join(tid3, NULL);
sem_destroy(&sem_a);
sem_destroy(&sem_b);
sem_destroy(&sem_c);
return 0;
}
2.进程间通信的方式:
1.管道
2.信号
3.消息队列
4.共享内存
5.有名信号量
6.本地域套接字
3.管道:
1.无名管道
只能用于具有亲缘关系的进程间通信
1.pipe
int pipe(int pipefd[2]);
功能:
创建一个无名管道,获得操作管道的两个文件描述符
pipefd[0]:读管道文件描述符
pipefd[1]:写管道文件描述符
返回值:
成功返回0
失败返回-1
无名管道就是一段内核缓存区
2.无名管道特点:
1.如果有写端:
1.如果有数据,直接读取数据
2.如果没有数据,阻塞等待直到读取到数据,再继续向下执行
2.如果没有写端:
1.如果有数据,直接读取数据
2.如果没有数据,不阻塞等待直接向下执行
3.如果有读端:
1.如果管道中没有写满(64k),则直接写入
2.如果管道中写满(64k),阻塞等待,直到有数据读出才能继续写入
4.如果没有读端:
1.向管道中写入数据会产生管道破裂,导致进程异常退出
2.有名管道
1.mkfifo
int mkfifo(const char *pathname, mode_t mode);
功能:
创建有名管道
参数:
pathname:有名管道路径
mode:权限
返回值:
成功返回0
失败返回-1
2.有名管道:
1.必须读写两端同时加入,才能继续向下执行
练习:
1.编程程序实现两个进程交替收发数据:
write.c read.c
从终端接收数据
发送给read.c
接收write.c内容
从终端接收数据
发送给write.c
hello world
thank you
aXX
XXX
ATOB.c
#include
#include
#include
#include
#include
#include
#include
int fdwrite;
int fdread;
int isRun = 1;
void *ChatWrite(void *arg)
{
fdwrite = open("./tmpBTOA", O_WRONLY);
while(isRun)
{
char tmpbuffer1[4096] = {0};
fgets(tmpbuffer1, sizeof(tmpbuffer1), stdin);
char *find = strchr(tmpbuffer1, '\n');
if(find)
{
*find = '\0';
}
if(0 == strcmp(tmpbuffer1, "quit"))
{
isRun = 0;
}
write(fdwrite, tmpbuffer1, strlen(tmpbuffer1));
}
return NULL;
}
void *ChatRead(void *arg)
{
fdread = open("./tmpATOB", O_RDONLY);
while(isRun)
{
char tmpbuffer2[4096] = {0};
read(fdread, tmpbuffer2, sizeof(tmpbuffer2));
if(0 == strcmp(tmpbuffer2, "quit"))
{
isRun = 0;
}
printf("RECV:%s\n", tmpbuffer2);
}
return NULL;
}
BTOA.c
int main(void)
{
pthread_t pid1;
pthread_t pid2;
mkfifo("./tmpBTOA", 0664);
pthread_create(&pid1, NULL, ChatWrite,NULL);
pthread_create(&pid2, NULL, ChatRead, NULL);
pthread_join(pid1, NULL);
pthread_join(pid2, NULL);
close(fdwrite);
close(fdread);
return 0;
}
#include
#include
#include
#include
#include
#include
#include
int fdwrite;
int fdread;
int isRun = 1;
void *ChatWrite(void *arg)
{
fdwrite = open("./tmpATOB", O_WRONLY);
while(isRun)
{
char tmpbuffer1[4096] = {0};
fgets(tmpbuffer1, sizeof(tmpbuffer1), stdin);
char *find = strchr(tmpbuffer1, '\n');
if(find)
{
*find = '\0';
}
if(0 == strcmp(tmpbuffer1, "quit"))
{
isRun = 0;
}
write(fdwrite, tmpbuffer1, strlen(tmpbuffer1));
}
return NULL;
}
void *ChatRead(void *arg)
{
fdread = open("./tmpBTOA", O_RDONLY);
while(isRun)
{
char tmpbuffer2[4096] = {0};
read(fdread, tmpbuffer2, sizeof(tmpbuffer2));
if(0 == strcmp(tmpbuffer2, "quit"))
{
isRun = 0;
}
printf("RECV:%s\n", tmpbuffer2);
}
return NULL;
}
int main(void)
{
pthread_t pid1;
pthread_t pid2;
mkfifo("./tmpATOB", 0664);
pthread_create(&pid1, NULL, ChatWrite, NULL);
pthread_create(&pid1, NULL, ChatRead, NULL);
pthread_join(pid1, NULL);
pthread_join(pid2, NULL);
close(fdwrite);
close(fdread);
return 0;
}