目录
4.2消息队列的API(msgget|msgsnd|msgrcv|msgctl)
5.2共享内存的API(shmget|shmat|shmdt|shmctl)
6.2信号灯集合API(semget|semctl|semop)
1.1使用信号量实现两个线程循环执行的过程
#include <head.h>
// 1.定义条件变量
pthread_cond_t cond;
pthread_mutex_t mutex;
int flags = 0;
//生产者线程
void* Task1(void* arg)
{
while (1) {
pthread_mutex_lock(&mutex);
while (flags == 1)
pthread_cond_wait(&cond, &mutex);
printf("我生产了一部Mate50保时捷版手机,售价12999\n");
flags = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
}
//消费者线程
void* Task2(void* arg)
{
while (1) {
pthread_mutex_lock(&mutex);
while (flags == 0)
pthread_cond_wait(&cond, &mutex);
printf("tid=%#lx,花重金购买了一部Mate50保时捷版手机\n", pthread_self());
flags = 0;
pthread_cond_signal(&cond);
sleep(1);
pthread_mutex_unlock(&mutex);
}
}
int main(int argc, const char* argv[])
{
pthread_t tid1, tid2;
// 2.初始化条件变量,初始化互斥锁
pthread_cond_init(&cond, NULL);
pthread_mutex_init(&mutex, NULL);
if (errno = pthread_create(&tid1, NULL, Task1, NULL))
PRINT_ERR("pthread create error");
if (errno = pthread_create(&tid2, NULL, Task2, NULL))
PRINT_ERR("pthread create error");
printf("tid2=%#lx\n", tid2);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
// 4.销毁
pthread_cond_destroy(&cond);
pthread_mutex_destroy(&mutex);
return 0;
}
1.2使用非阻塞方式回收子进程的资源
#include <head.h>
char buf[128] = {0};
void signal_handle(int signo)
{
printf("我收到了子进程退出的信号SIGCHLD\n");
printf("我在使用非阻塞方式回收子进程的资源\n");
waitpid(-1,NULL,WNOHANG);
system(buf);
}
int main(int argc, const char* argv[])
{
pid_t pid;
snprintf(buf,sizeof(buf),"kill -9 %d",getpid());
pid = fork();
if (pid == -1) {
PRINT_ERR("fork error");
} else if (pid == 0) {
printf("child:pid = %d,ppid=%d\n", getpid(), getppid());
sleep(3);
exit(EXIT_SUCCESS);
} else {
printf("parent:pid = %d,cpid = %d,ppid=%d\n", getpid(), pid, getppid());
if(SIG_ERR == signal(SIGCHLD,signal_handle))
PRINT_ERR("register signal error");
while(1);
}
return 0;
}
1.3捕捉管道破裂信号
#include <head.h>
void signal_handle(int signo)
{
printf("我收到了管道破裂的信号\n");
}
int main(int argc, const char* argv[])
{
int pipefd[2];
char buf[128] = "hello everyone!!!";
// 0.注册信号处理函数
if (SIG_ERR == signal(SIGPIPE, signal_handle))
PRINT_ERR("register signal error");
// 1.创建无名管道
if (pipe(pipefd))
PRINT_ERR("create pipe error");
// 2.关闭读端
close(pipefd[0]);
// 3.写管道 (管道破裂)
write(pipefd[1], buf, strlen(buf));
while (1);
return 0;
}
2.信号
2.1发信号的函数
int kill(pid_t pid, int sig);
功能:发信号的函数
参数:
@pid: 进程号
pid > 0 :将信号发送给这个pid对应的进程
pid = -1 :给有权限的所有进程发送信号,init除外
pid = 0 :信号将发送给同组的所有的进程
pid < -1 :对pid取绝对值,和这个pid同组的所有的进程都能收到信号
@sig: 信号号
返回值:成功返回0,失败返回-1置位错误码
int raise(int sig);
功能:给自己发信号
参数:
@sig:信号号
返回值:成功返回0,非0是失败
unsigned int alarm(unsigned int seconds);
功能:当 seconds倒计时为0的时候,给当前进程发送一个闹钟信号
参数:
@seconds:秒钟
>0 倒计时到0的时候会发出闹钟信号
=0 倒计时到0的时候不会发出闹钟信号
返回值:如果alarm第一调用返回0,如果不是第一次调用返回上一次的剩余秒钟数
2.2kill函数使用实例
#include <head.h>
void signal_handle(int signo)
{
printf("我收到了子进程退出的信号SIGCHLD\n");
printf("我在使用非阻塞方式回收子进程的资源\n");
waitpid(-1,NULL,WNOHANG);
kill(getpid(),SIGKILL);
}
int main(int argc, const char* argv[])
{
pid_t pid;
pid = fork();
if (pid == -1) {
PRINT_ERR("fork error");
} else if (pid == 0) {
printf("child:pid = %d,ppid=%d\n", getpid(), getppid());
sleep(3);
exit(EXIT_SUCCESS);
} else {
printf("parent:pid = %d,cpid = %d,ppid=%d\n", getpid(), pid, getppid());
if(SIG_ERR == signal(SIGCHLD,signal_handle))
PRINT_ERR("register signal error");
while(1);
}
return 0;
}
#include <head.h>
//./a.out 22300
int main(int argc,const char * argv[])
{
kill(atoi(argv[1]),SIGKILL);
return 0;
}
2.3raise函数实例
#include <head.h>
void signal_handle(int signo)
{
printf("我收到了子进程退出的信号SIGCHLD\n");
printf("我在使用非阻塞方式回收子进程的资源\n");
waitpid(-1,NULL,WNOHANG);
// kill(getpid(),SIGKILL);
raise(SIGKILL);
}
int main(int argc, const char* argv[])
{
pid_t pid;
pid = fork();
if (pid == -1) {
PRINT_ERR("fork error");
} else if (pid == 0) {
printf("child:pid = %d,ppid=%d\n", getpid(), getppid());
sleep(3);
exit(EXIT_SUCCESS);
} else {
printf("parent:pid = %d,cpid = %d,ppid=%d\n", getpid(), pid, getppid());
if(SIG_ERR == signal(SIGCHLD,signal_handle))
PRINT_ERR("register signal error");
while(1);
}
return 0;
}
2.4alarm函数实例
#include <head.h>
void handle(int signo)
{
if (signo == SIGALRM) {
printf("我收到了闹钟信号\n");
}
}
int main(int argc, const char* argv[])
{
if (SIG_ERR == signal(SIGALRM, handle))
PRINT_ERR("register siganl error");
//第一调用alarm的时候返回值是0
printf("%d\n",alarm(5));
sleep(2);
//第二次调用的时候alarm返回值是3
//但是由于将倒计时又设置为了5,
//5秒之后会执行信号处理函数
printf("%d\n",alarm(5));
while(1);
return 0;
}
2.5alarm函数使用(斗地主倒计时)
#include <head.h>
void handle(int signo)
{
printf("系统自动出牌成功了\n");
alarm(4);
}
int main(int argc, const char* argv[])
{
char ch;
if (SIG_ERR == signal(SIGALRM, handle))
PRINT_ERR("register siganl error");
alarm(4);
while(1){
ch = getchar();
getchar(); //吃掉垃圾字符'\n'
printf("手动出牌 = %c\n",ch);
alarm(4);
}
return 0;
}
3.IPC进程间通信
3.1IPC进程间通信的种类
1.消息队列
2.共享内存
3.信号灯集
3.2IPC进程间通信用到的命令
(1)查看(ipcs)
ipcs -q //查看消息队列
ipcs -m //查看共享内存
ipcs -s //查看信号灯集
(2)删除(ipcrm)
ipcrm -q msqid //删除消息队列
ipcrm -m shmid //删除共享内存
ipcrm -s semid //删除信号灯集
3.3IPC通信键值的获取
#inc