Linux中进程间通信与同步

一、进程间通信

进程间通信

1.管道、信号 //最早出现的两种方式

2.消息队列

共享内存

信号灯 //工程一般用的三种

3.套接字 //教育用的

本文列举1和2中的通信方式

1.管道

最简单的通信方式

管道分类

1.有名管道

2.无名管道

1.无名管道

管道是一段内核缓存区

只能用于具有亲缘关系的进程间通信

  1. 函数接口
pipe
int pipe(int pipefd[2]);
功能:
    创建一个管道
参数:
    pipefd[2]:一个两个元素的数组,用来存放读写文件描述符
返回值:
    成功返回0 
    失败返回-1 
2.管道特性

管道缓存区 64k

管道中至少有一个写端:
        如果管道中有数据直接读取数据
        如果管道中没有数据阻塞等待直到有数据写入再读出数据
管道中没有写端:
        如果管道中有数据直接读取数据 
        如果管道中没有数据不阻塞等待直接继续向下执行
管道中至少有一个读端:
        管道中数据没有写满,则直接写入数据
        管道中数据已满,阻塞等待,等到有数据被读出才能继续写入
管道中没有读端:
        管道中写入数据会产生管道破裂,进程异常结束

2.有名管道

函数接口
mkfifo
  int mkfifo(const char *pathname, mode_t mode);
  功能:
    创建一个管道文件
  参数:
    pathname:管道文件路径
    mode:管道文件权限
  返回值:
    成功返回0 
    失败返回-1 

注意:

有名管道必须读写两端都加入后,才能继续向下执行

2.信号:

1.信号的种类

1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP

6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1

11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM

16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP

21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ

26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR

31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3

38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8

43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47)SIGRTMIN+13

48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12

53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7

58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2

63) SIGRTMAX-1 64) SIGRTMAX

常用的几种:

SIGINT:ctrl + c

SIGQUIT:ctrl + \

SIGSEGV:段错误信号

SIGPIPE:管道破裂信号

SIGALRM:定时信号

SIGIO:异步IO

SIGTSTP:挂载信号 ctrl + z

SIGSTOP:暂停信号

SIGCONT:继续信号

SIGCHLD:子进程结束信号

以下信号不允许被忽略和捕捉:

9: SIGKILL

19: SIGSTOP

2.信号的处理方式

1.缺省

按照默认方式处理信号

2.忽略

不处理信号

3.捕捉

按照自定义方式处理信号

3.函数接口:
1.signal
typedef void (*sighandler_t)(int);
        sighandler_t signal(int signum, sighandler_t handler);
    功能:
        设置信号的处理方法
            1.缺省(按照默认方式处理信号)
            2.忽略(不处理信号)
            3.捕捉(按照handler对应的方式处理信号)
    参数:
        signum:信号的编号
        handler:信号的处理方式
        SIG_IGN 忽略
        SIG_DFL 缺省 
    返回值:
        成功返回之前处理信号的方式
        失败返回SIG_ERR
2.pause
int pause(void);
  功能:
    让进程任务挂起
  参数:
    缺省
  返回值:
    成功任务挂起
    被唤醒返回-1 
3.alarm
unsigned int alarm(unsigned int seconds);
  功能:
    过seconds秒后,给进程发送SIGALRM信号
  参数:
    seconds:秒数
  返回值:
    返回上次定时剩余的秒数
4.kill
int kill(pid_t pid, int sig);
  功能:
    向pid对象的进程发送一个sig信号
  参数:
    pid:接收进程信号的ID
    sig:信号的编号
  返回值:
    成功返回0 
    失败返回-1 

3.消息队列:

IPC对象(内存文件)

生成key值 -> 创建消息队列 -> 发送/接收消息 -> 删除

1.查看所有IPC对象命令
ipcs
2.删除IPC对象命令
ipcrm

ipcrm -q/-m/-s msgid/shmid/semid 删除消息队列/共享内存/信号量数组(信号灯)

ipcrm -Q/-M/-S key

3.函数接口:
1.ftok
key_t ftok(const char *pathname, int proj_id);
  功能:
    根据pathname和proj_id生成一个IPC对象名字
  参数:
    pathname:路径
    proj_id:项目ID(8位)
  返回值:
    成功返回key_t类型的IPC对象名
    失败返回-1 
2.msgget
int msgget(key_t key, int msgflg);
  功能:
    创建一个消息队列
  参数:
    key:键值
    msgflg:
        IPC_CREAT 没有就创建
        IPC_EXCL 如果之前已经创建了消息队列,会报错
  返回值:
    成功返回消息队列的ID
    失败返回-1 
3.msgsnd
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
  功能:
    向消息队列中发送消息
  参数:
    msqid:消息队列ID号 
    msgp:发送消息结构体空间首地址
    msgsz:发送消息内容
    msgflg:默认为0 
  返回值:
    成功返回0 
    失败返回-1 
4.msgrcv
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
  功能:
    从消息队列中接收消息
  参数:
    msqid:消息队列ID号
    msggp:存放接收到消息空间首地址
    msgsz:接收消息的大小
    msgtyp:消息队列的类型 
    msgflg:接收消息的标志 默认为0 
  返回值:
    成功返回实际接收消息的字节数
    失败返回-1 
5.msgctl
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
  功能:
    向消息队列发送一条命令
  参数:
    msqid:消息队列ID号
    cmd:
        IPC_STAT 获得消息队列属性
        IPC_SET 设置消息队列权限
        IPC_RMID 删除消息队列
    buf:
        根据命令传递内容不同
  返回值:
     成功返回0 
     失败返回-1 

4.共享内存

进程间通信最高效

生成key值 -> 创建共享内存 -> 映射 -> 操作数据 -> 解除映射 -> 删除共享内存

函数接口:
1.shmget
int shmget(key_t key, size_t size, int shmflg);
  功能:
    创建一个共享内存空间
  参数:
    key:IPC对象名
    size:共享内存空间大小
    shmflg:
        IPC_CREAT
    IPC_EXECL
  返回值:
    成功返回共享内存ID
    失败返回-1 
2.shmat
void *shmat(int shmid, const void *shmaddr, int shmflg);
  功能:
    将进程空间地址映射到共享内存
  参数:
    shmid:共享内存ID号 
    shmaddr:
        NULL 系统选择一个合适的地址映射
  返回值:
    成功返回映射到共享内存空间中的地址
    失败返回-1 
3.shmdt
int shmdt(const void *shmaddr);
  功能:
    解除映射 
  参数:
    shmaddr:共享内存空间的地址
  返回值:
    成功返回0 
    失败返回-1 
4.shmctl
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
  功能:
    向共享内存中发送一条命令
  参数:
    shmid:共享内存ID号 
    cmd:
        IPC_STAT 
        IPC_SET 
        IPC_RMID 删除 
    buf:
        NULL
  返回值:
    成功返回0 
    失败返回-1 

5.信号量数组(信号灯)

也称有名信号量(线程中同步信号称无名信号量)

函数接口
1.ftok
2.semget
int semget(key_t key, int nsems, int semflg);
  功能:
    创建信号量数组
  参数:
    key:键值
    nsems:信号量的个数
    semflg:
        IPC_CREAT 
        IPC_EXCL
  返回值:
    成功返回信号量ID
    失败返回-1 
3.semctl
int semctl(int semid, int semnum, int cmd, ...);
  功能:
    向信号量发送一条命令
  参数:
    semid:信号量的ID号 
    semnum:信号量的编号
    cmd:
        IPC_SET
        IPC_STAT
        IPC_RMID 
        SETVAL 设置初值
  返回值:
        成功返回0
        失败返回-1 
4.semop
int semop(int semid, struct sembuf *sops, size_t nsops);
  功能:
    申请和释放信号量
  参数:
    semid:信号量的ID号 
    sops:申请释放操作信号量的数组空间首地址
    nsops:对信号量操作的数组长度
  返回值:
    成功返回0 
    失败返回-1 

struct sembuf内容

           unsigned short sem_num;  /* semaphore number */
           short          sem_op;   /* semaphore operation */
           short          sem_flg;  /* operation flags */

附加

(消息队列+共享内存+信号灯) 都可在ipcs查看

二、进程间同步

信号灯即可实现

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值