1,管道(Pipe)及有名管道(named pipe)
管道可用于具有亲缘关系进程间的通信
有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;
2,信号(Signal):,
3,消息队列(Message):
消息队列是消息的链接表,包括Posix消息队列system V消息队列
消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
4,共享内存:
使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
5,信号量(Semaphore):
主要作为进程间以及同一进程不同线程之间的同步手段。
6,套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。
参考https://www.cnblogs.com/cfans1993/p/5657478.html
https://www.cnblogs.com/52php/p/5878029.html
https://www.cnblogs.com/52php/p/5840229.html
管道是Linux支持的最初Unix IPC形式之一,具有以下特点:
#include <unistd.h>
int pipe(int fd[2])
当管道的写端存在时,数据不能超过PIPE_BUF 注:(不同系统要求的PIPE_BUF不一样,通常为512字节)。
#include <stdio.h>
FILE* popen(const char *command, const char *open_mode);
int pclose(FILE *stream_to_close);
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#define MAXLINE 1024
void err_quit(const char *str){
perror(str);
exit(1);
}
int main(){
char line[MAXLINE];
FILE *fpin;
if((fpin=popen("ls -l","r")) == NULL)
err_quit("popen error");
while(fgets(line,MAXLINE,fpin) != NULL){
if(fputs(line,stdout) ==EOF)
err_quit("fputs error");
}
if(ferror(fpin))
err_quit("fpin error");
if(pclose(fpin)==-1)
err_quit("pclose error");
return 0;
}
由于信号量只能进行两种操作等待和发送信号,即P(sv)和V(sv),他们的行为是这样的:
P(sv):如果sv的值大于零,就给它减1;如果它的值为零,就挂起该进程的执行
V(sv):如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,就给它加1.
举个例子,就是两个进程共享信号量sv,一旦其中一个进程执行了P(sv)操作,它将得到信号量,并可以进入临界区,使sv减1。而第二个进程将被阻止进入临界区,
因为当它试图执行P(sv)时,sv为0,它会被挂起以等待第一个进程离开临界区域并执行V(sv)释放信号量,这时第二个进程就可以恢复执行。
它的作用是创建一个新信号量或取得一个已有信号量,原型为:
int semget(key_t key, int num_sems, int sem_flags);
key是整数值(唯一非零),不相关的进程可以通过它访问一个信号量,比如每个进程都调用:
sem_id = semget((key_t) 1234, 1, 0666 | IPC_CREAT);就可以访问同一个信号量
它的作用是改变信号量的值,原型为:
int semop(int sem_id, struct sembuf *sem_opa, size_t num_sem_ops);
参考:https://www.cnblogs.com/52php/p/5861372.html
4.1概念
不同进程之间共享的内存通常安排为同一段物理内存。通常与信号量一起用。
4.2 函数
int shmget(key_t key, size_t size, int shmflg);//不同的进程使用相同的key值,通常置为整形,就可以访问同一块共享内存
void *shmat(int shm_id, const void *shm_addr, int shmflg); // attach启动对该共享内存的访问,可以用memcpy直接操作空间
int shmdt(const void *shmaddr); //detach 该函数用于将共享内存从当前进程中分离。注意,将共享内存分离并不是删除它,只是使该共享内存对当前进程不再可用。
int shmctl(int shm_id, int command, struct shmid_ds *buf); //用来控制共享内存
5.1 概念
消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。 消息队列与命名管道一样,每个发送的数据块都有最大长度的限制。Linux用宏MSGMAX和MSGMNB来限制一条消息的最大长度和一个队列的最大长度。
5.2 函数
int msgget(key_t, key, int msgflg);//创建和访问消息队列
int msgsend(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);//把消息添加到消息队列中
int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg);//从一个消息队列获取消息
int msgctl(int msgid, int command, struct msgid_ds *buf);//控制消息队列
https://www.cnblogs.com/52php/p/5872596.html
6.1 概念
套接字的特性由3个属性确定,它们分别是:域、类型和协议。
套接字的域:
AF_INET,它指的是Internet网络
AF_UNIX表示UNIX文件系统,它就是文件输入/输出,而它的地址就是文件名。
套接字类型
流套接字 SOCK_STREAM: TCP
数据报套接字SOCK_DGRAM :UDP
不同的域,有不同的套接字地址格式
对于AF_UNIX域套接字来说,它的地址由结构sockaddr_un来描述,该结构定义在头文件sys/un.h中,它的定义如下:
1
2
3
4
|
struct sockaddr_un { sa_family_t sun_family; // AF_UNIX,它是一个短整型 char sum_path[]; // 路径名 }; |
对于AF_INET域套接字来说,它的地址结构由sockaddr_in来描述,它至少包括以下几个成员:
1
2
3
4
5
|
struct sockaddr_in { short int sin_family; //AF_INET unsigned short int sin_port; //端口号 struct in_addr sin_addr; //IP地址 }; |
6.3 基于流套接字(tcp)的客户/服务器的工作流程
6.3.1 服务器
socket-》bind-》listen-》accept
6.3.1 客户端
socket-》connect
6.4 基于流套接字(tcp)的客户/服务器的工作流程
6.4.1 服务器
socket-》bind-》recvfrom/sendto
6.4.1 客户端
socket-》recvfrom/sendto
七,信号
https://www.cnblogs.com/52php/p/5813867.html
信号的名称是在头文件signal.h中定义的,信号都以SIG开头,常用的信号并不多,常用的信号如下:
更多的信号类型可查看附录表。
原文:https://www.cnblogs.com/shelley-AL/p/10717714.html