进程间通信

线程间同步机制:让多个线程在执行某个任务时具有先后顺序的执行;

异步:多线程、多进程本质是异步执行;

让多线程在执行时具有先后顺序

信号量:实现线程间同步;

操作步骤:

1.定义信号量对象:sem_t;

2.初始化信号量;

3.PV操作(申请p与释放v信号量);

        申请:sem_wait(&sem_w);

        释放:sem_post(&sem_r);

4.销毁信号量:sem_destroy(&);

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

#include<semaphore.h>

功能:初始化信号量;

参数:

        sem:要初始化信号量的地址;

        pshared:

                0:线程间共享;

                !0:进程间共享;

                value:信号量的初始值(初始资源数)

返回值:

        成功:0;

        失败:-1

例(使用三个线程按顺序打印A,B,C):

#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
#include<unistd.h>

char buff[3] = {'A','B','C'};

sem_t sem1;
sem_t sem2;
sem_t sem3;

void *task1(void *arg)
{
    while(1)
    {
        sem_wait(&sem1);
        printf("task1 = %c\n",buff[0]);
        sleep(1);
        sem_post(&sem2);
    }
}

void *task2(void *arg)
{
    while(1)
    {
        sem_wait(&sem2);
        printf("task2 = %c\n",buff[1]);
        sleep(1);
        sem_post(&sem3);
    }
}

void *task3(void *arg)
{
    while(1)
    {
        sem_wait(&sem3);
        printf("task3 = %c\n",buff[2]);
        sleep(1);
        sem_post(&sem1);
    }
}



int main(void)
{
    pthread_t tid[3];

    sem_init(&sem1,0,1);
    sem_init(&sem2,0,0);
    sem_init(&sem3,0,0);

    pthread_create(&tid[0],NULL,task1,NULL);
    pthread_create(&tid[1],NULL,task2,NULL);
    pthread_create(&tid[2],NULL,task3,NULL);

    pthread_join(tid[0],NULL);
    pthread_join(tid[1],NULL);
    pthread_join(tid[2],NULL);

    sem_destroy(&sem1);
    sem_destroy(&sem2);
    sem_destroy(&sem3);

    return 0;
}

互斥锁、信号量、读写锁、自旋锁------>锁

死锁:死锁指的是在多线程环境中,每个执行流(线程)都有未被释放的资源,且互相请求对方未释放资源,从而导致陷入永久等待的情况;

现象:

现象1:忘记释放锁;

现象2:重复加锁;

现象3:多线程加锁,抢占资源不当;

产生死锁的四个必要条件:

(1)互斥条件:一个资源每次只能被一个进程使用;

(2)请求与保持条件:进程因请求资源而阻塞时,对已获得的资源保持不放;

(3)不可剥夺条件:进程以获得的资源,在未使用完之前,不能强行剥夺;

(4)循环等待条件:若干进程之间形成一种头尾相连的循环等待资源关系;

解决办法:

(1)锁一定要成对出现;

(2)使线程的加锁顺序一致;

(3)破坏环路等待条件;

非阻塞锁   pthread_mutex_trylock()

多任务并发:

1.多进程;

2.多线程;

3.IPC机制(进程间通信的通信机制)

        原因:因为进程间空间是独立的,不能直接通信;

同一主机进程间通信:

1.古老的通信方式

        无名管道;

        有名管道;

        信号:进程间通知机制;

2.IPC对象通信  system v

        共享内存(效率最高);

        消息队列;

        信号量集(信号灯);

主要在不同主机进程间通信

3.socket通信

        网络通信

IPC机制:

1.管道

        有名管道:可以用于同一主机,任意进程间通信;

        无名管道:只能用于同一主机,具有亲缘关系的进程(父子进程);

2.无名管道

        每个进程的内核是共用的,另外的0-3G是独立的,无名管道在内核中创立一个空间,其他进程能够对该空间进行读写操作(无名);

        (1)无名管道操作流程

                <1>创建无名管道:pipe();  成功:0

                        pipefd[0] ----->读端;

                        pipefd[1]------>写端;

                <2>写管道---->write();

                <3>写管道---->read();

                <4>关闭管道---->close();

void *memset(void *s,int c,size_t n);

功能:将内存区域填充成指定的数据;

(2)管道本质:

        内核空间中的一段缓冲区,遵顼先入先出特点

        无名管道的:读端:pipefd[0];

                               写端:pipefd[1];

                                二者不能交换

(3)管道的特性:

        (1) 写阻塞:读端与写端都存在,向管道中写数据,当管道满时,发生写阻塞;

        (2)读阻塞:读端与写端都存在,向管道中读数据,当管道为空,发生读阻塞;

        (3)读返回0:当写端关闭,从管道中读数据,若管道中有数据,则读到数据;若管道中没有数据,返回0,不再阻塞;

        (4)管道破裂:读端关闭,向管道中写入数据,发生管道破裂(异常)

通信方式:v

单工:广播;

半双工:对讲机

全双工:电话

3.有名管道

与无名管道类似,不过内核中管道开辟的空间(缓冲区)与文件(管道文件)相关联。

有名管道的操作流程:

        1.创建一个管道文件:mkfifo、mkfifo():

        2.打开管道文件:open;

        3.读/写管道文件:read、write;

        4.关闭管道文件close;

                int  mkfifo(const  char  *pathname,mode_t  mode)

                功能:创建一个管道;

                参数:

                        pathename:文件名;

                        mode:管道文件的读写执行权限;

                返回值:

                        成功:0;

                        失败:-1;

4.信号     

信号:实现进程间的通知机制

        实现进程间的异步通信

        软中断

异步通信:接收方不知道什么时候发送方什么时候发送数据;

(1)系统支持的信号有哪些

        kill  -l   查看

        2)SIGUNT: CTRL   +   C

        打断进程

        3)SIGQUIT   ctrl  +   \

        使进程结束

        9)SIGKILL

        杀死进程(管理员信号结束90%进程)

        10)SIGUSR1

        用户自定义的信号

        11)SIGSIGV

        进程强制中止(段错误信号)

        12)SIGUSR2

        用户自定义的信号

        13)SIGPIPE

        管道破裂时发送出来的信号

        14)SIGALRM

        让一个进程结束(定时到达)

        17)SIGCHLD

        子进程要结束发给父进程(自动)

        18)SIGCONT

        进程从暂停态继续运行

        19)SIGSTOP

        进程进入暂停态(管理员信号)

        20)SIGTSTP

        ctrl  +  Z让进程进入暂停态,变为后台进程

(2)信号的处理流程

        <1>  缺省(xing):按照默认处理方式处理;

        <2>  忽略:不处理;

        <3>  捕获:以自定义方式处理;

signal:

        #include <signal.h>

       typedef void (*sighandler_t)(int);

       sighandler_t signal(int signum, sighandler_t handler);

功能:设置处理信号的方式(注册一个信号)

参数:

        signum:要处理的信号的编号;

        handler:

                        SIG_IGN:以忽略方式处理该信号(不处理);

                        SIG_DFL:以缺省方式处理(默认);

                        函数的地址:以捕获的方式处理(自定义);

返回值:

        失败:NULL;

        自定义方式时:返回自定义的函数入口;

void(*sighandler_t)(int  signum)

        sighandler_t :

注意:

        1.若信号不被注册,则按照默认方式处理;

        2.信号只需注册一次即可;

        3.每次信号的到来都会触发一次任务处理函数;

        4.信号需要早注册;

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值