linux基础——IPC进程间通信

简介: linux基础——IPC进程间通信

文章目录

IPC进程间通讯

消息队列

向消息队列发送消息和接收消息

代码示例

共享内存

代码示例

信号量集

代码示例


IPC进程间通讯

使用命令ipcs可以查看IPC的对象。

2020020619540153.png

ftok


#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
功能:转换pathname和proj_id为一个key值
参数:
pathname:指定文件的名字
proj_id:一个整数,这个整数的低8位不能为0
返回值:
成功  key值返回
-1  失败  errno被设置


1.第一步,获取一个键值。

2. 第二步,通过键值获取一块内存,将这块内存的id返回。

3. 第三部,通过内存id来操作这块内存。


代码示例


  • ftok.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
int main(void){
  key_t key;
  //获取键值
  key=ftok("hello",32);
  if(key==-1){
  perror("ftok");
  return 1;
  }
  printf("key=%d\n",key);
  return 0;
}


  • 执行结果

20200206200254625.png

消息队列

通过键值获取一块内存,将这块内存的id返回,需要使用到msgget获取内核内存的id。


#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
功能:获取一个消息队列的id
参数:
key:fotk(3)获取到的键值
msgflg:
IPC_CREAT:
IPC_EXCL:
mode:  指定了消息队列的权限
返回值:
-1  失败   errno被设置
成功返回消息队列的id


代码示例

通过键值获取消息队列的id


  • msgget.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int main(void){
  key_t key;
  //获取键值
  key=ftok("hello",31);
  if(key==-1){
  perror("ftok");
  return 1;
  }
  printf("key=%x\n",key);
  //通过键值获取消息队列的id
  int msqid=msgget(key,IPC_CREAT|0664);
  if(msqid==-1){
  perror("msgget");
  return 2;
  }
  printf("msgqid=%d\n",msqid);
  return 0;
}


  • 执行结果

20200206200947841.png

向消息队列发送消息和接收消息

msgsnd


#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid,const void *msgp,size_t msgsz,\
  int msgflg);
功能:向消息队列发送消息
参数:
msqid:指定了要操作的消息队列的id
msgp:指向struct msgbuf类型的变量的指针
msgsz:是mtext的长度
msgflg:
IPC_NOWAIT   在空间不够的情况下,非阻塞等待,立即返回错误
0     空间不够的情况下,等待空间充足才解除阻塞
返回值:
0  成功
-1  失败  errno被设置


msgrcv


ssize_t msgrcv(int msqid, void *msgp, size_t msgsz,\
   long msgtyp,int msgflg);
功能:从消息队列中获取消息
参数:
msqid:指定了消息队列的id
msgp:指向了获取到的消息
msgsz:是mtext的长度
msgtyp:消息的类型
msgflg:
IPC_NOWAIT:如果消息队列中没有消息,立即返回
0:如果消息队列中没有消息,阻塞等待
返回值:
-1  错误  errno被设置
获取到的消息体的字节数


代码示例

将一个消息放入消息队列中。


  • processA.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
typedef struct msgbuf{
  long mtype;
  char mtext[256];
}msgbuf_t;
int main(void){
  key_t key;
  msgbuf_t mb;//消息类型的变量
  //获取key值
  key=ftok("hello",31);
  if(key==-1){
  perror("ftok");
  return 1;
  }
  //获取消息队列的id
  int msqid=msgget(key,IPC_CREAT|0664);
  if(msqid==-1){
  perror("msgget");
  return 2;
  }
  //初始化消息
  mb.mtype=3;/*must be >0*/
  strcpy(mb.mtext,"this is test\n");
  //向消息队列中写入消息
  int s=msgsnd(msqid,&mb,strlen(mb.mtext)+1,0);
  if(s==-1){
  perror("msgsnd");
  return 3;
  }
  return 0;
}


从消息队列中获取消息并显示


  • processB.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
typedef struct msgbuf{
  long mtype;
  char mtext[256];
}msgbuf_t;
int main(void){
  key_t key;
  msgbuf_t mb;//消息类型的变量
  //获取key值
  key=ftok("hello",31);
  if(key==-1){
  perror("ftok");
  return 1;
  }
  //获取消息队列的id
  int msqid=msgget(key,IPC_CREAT|0664);
  if(msqid==-1){
  perror("msgget");
  return 2;
  }
  //从消息队列中获取消息
  int s=msgrcv(msqid,&mb,256,3,0);
  if(s==-1){
  perror("msgrcv");
  return 3;
  }
  printf("%s",mb.mtext);
  return 0;
}


  • 执行结果

20200206202123367.png

共享内存

根据键值获取共享内存的id,通过shmget获取共享内存id。

int shmget(key_t key, size_t size, int shmflg);

#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
功能:
参数:
key:ftok(3)返回的键值
size:指定了共享内存的尺寸
shmflg:
IPC_CREAT:指定创建共享内存段
IPC_EXCL:
mode:
返回值:
-1  错误
返回共享内存段的id


将共享内存映射到进程的虚拟地址空间中,使用shmat

shmat(2)


#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:将共享内存绑定到进程的地址空间里
参数:
shmid:共享内存的id
shmaddr:指定了进程绑定共享内存的地址。指定为NULL,有系统做选择
shmflg:
SHM_RDONLY:共享内存段只读
返回值:
返回和共享内存段绑定的地址
 (void *) -1  错误  errno被设置


*int shmdt(const void shmaddr);


功能:解除和共享内存段的绑定
参数:
shmaddr:指定了要解除的共享内存段在进程中的地址
返回值:
0  成功
-1  失败 errno被设置


代码示例

创建共享内存段。


  • shm.c
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
int main(void){
  key_t key;
  //获取键值
  key=ftok("hello",41);
  if(key==-1){
  perror("ftok");
  return 1;
  }
  printf("key:%d\n",key);
  //根据键值获取shmid
  int shmid=shmget(key,1024,\
    IPC_CREAT|0664);
  if(shmid==-1){
  perror("shmget");
  return 2;
  }
  printf("获取到共享内存%d\n",shmid);
  return 0;
}


  • 执行结果

20200206203046194.png

使用共享内存完成进程间通信:


  • shmA.c
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>
int main(void){
  key_t key;
  //获取键值
  key=ftok("hello",41);
  if(key==-1){
  perror("ftok");
  return 1;
  }
  printf("key:%d\n",key);
  //根据键值获取shmid
  int shmid=shmget(key,1024,\
    IPC_CREAT|0664);
  if(shmid==-1){
  perror("shmget");
  return 2;
  }
  printf("获取到共享内存%d\n",shmid);
  //将共享内存映射到进程的虚拟地址空间
  void *p=shmat(shmid,NULL,0);
  if(p==(void *) -1){
  perror("shmat");
  return 3;
  }
  //拷贝字符串到共享内存段
  strcpy(p,"hello tarena\n");
  //解除绑定
  shmdt(p);
  return 0;
}


  • shmB.c
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>
int main(void){
  key_t key;
  //获取键值
  key=ftok("hello",41);
  if(key==-1){
  perror("ftok");
  return 1;
  }
  printf("key:%d\n",key);
  //根据键值获取shmid
  int shmid=shmget(key,1024,\
    IPC_CREAT|0664);
  if(shmid==-1){
  perror("shmget");
  return 2;
  }
  printf("获取到共享内存%d\n",shmid);
  //将共享内存映射到进程的虚拟地址空间
  void *p=shmat(shmid,NULL,0);
  if(p==(void *) -1){
  perror("shmat");
  return 3;
  }
  //将共享内存段的内容输出到显示器
  printf("%s",(char *)p);
  //解除绑定
  shmdt(p);
  return 0;
}


  • 执行结果


信号量集

具体参考代码示例


代码示例

  • mycp.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void copy_file(int s,int d){
  int r,w;
  char buf[1024];
  char *tmp;
  r=read(s,buf,1024);
  while(r>0){
  tmp=buf;
  while(1){//将读出的内容完全写入到目标文件
    w=write(d,tmp,r);
    r=r-w;
    tmp+=w;
    if(r==0)break;
  }
  r=read(s,buf,1024);
  }
  return; 
}
int main(int argc,char *argv[]){
  int s_fd,d_fd;
  //以只读方式打开源文件
  s_fd=open(argv[1],O_RDONLY);
  if(s_fd==-1){
  perror("open s");
  return 1;
  }
  //以写的方式打开目标文件
  d_fd=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0664);
  if(d_fd==-1){
  perror("open d");
  return 2;
  }
  copy_file(s_fd,d_fd);
  close(s_fd);
  close(d_fd);
  return 0;
}


  • 执行结果

20200206204426696.png

相关文章
|
11天前
|
缓存 监控 Linux
linux进程管理万字详解!!!
本文档介绍了Linux系统中进程管理、系统负载监控、内存监控和磁盘监控的基本概念和常用命令。主要内容包括: 1. **进程管理**: - **进程介绍**:程序与进程的关系、进程的生命周期、查看进程号和父进程号的方法。 - **进程监控命令**:`ps`、`pstree`、`pidof`、`top`、`htop`、`lsof`等命令的使用方法和案例。 - **进程管理命令**:控制信号、`kill`、`pkill`、`killall`、前台和后台运行、`screen`、`nohup`等命令的使用方法和案例。
39 4
linux进程管理万字详解!!!
|
2天前
|
存储 运维 监控
深入Linux基础:文件系统与进程管理详解
深入Linux基础:文件系统与进程管理详解
33 8
|
11天前
|
算法 Linux 定位技术
Linux内核中的进程调度算法解析####
【10月更文挑战第29天】 本文深入剖析了Linux操作系统的心脏——内核中至关重要的组成部分之一,即进程调度机制。不同于传统的摘要概述,我们将通过一段引人入胜的故事线来揭开进程调度算法的神秘面纱,展现其背后的精妙设计与复杂逻辑,让读者仿佛跟随一位虚拟的“进程侦探”,一步步探索Linux如何高效、公平地管理众多进程,确保系统资源的最优分配与利用。 ####
39 4
|
12天前
|
缓存 负载均衡 算法
Linux内核中的进程调度算法解析####
本文深入探讨了Linux操作系统核心组件之一——进程调度器,着重分析了其采用的CFS(完全公平调度器)算法。不同于传统摘要对研究背景、方法、结果和结论的概述,本文摘要将直接揭示CFS算法的核心优势及其在现代多核处理器环境下如何实现高效、公平的资源分配,同时简要提及该算法如何优化系统响应时间和吞吐量,为读者快速构建对Linux进程调度机制的认知框架。 ####
|
13天前
|
消息中间件 存储 Linux
|
19天前
|
运维 Linux
Linux查找占用的端口,并杀死进程的简单方法
通过上述步骤和命令,您能够迅速识别并根据实际情况管理Linux系统中占用特定端口的进程。为了获得更全面的服务器管理技巧和解决方案,提供了丰富的资源和专业服务,是您提升运维技能的理想选择。
20 1
|
1月前
|
算法 Linux 调度
深入理解Linux操作系统的进程管理
【10月更文挑战第9天】本文将深入浅出地介绍Linux系统中的进程管理机制,包括进程的概念、状态、调度以及如何在Linux环境下进行进程控制。我们将通过直观的语言和生动的比喻,让读者轻松掌握这一核心概念。文章不仅适合初学者构建基础,也能帮助有经验的用户加深对进程管理的理解。
20 1
|
1月前
|
消息中间件 Linux API
Linux c/c++之IPC进程间通信
这篇文章详细介绍了Linux下C/C++进程间通信(IPC)的三种主要技术:共享内存、消息队列和信号量,包括它们的编程模型、API函数原型、优势与缺点,并通过示例代码展示了它们的创建、使用和管理方法。
29 0
Linux c/c++之IPC进程间通信
|
4月前
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能
|
4月前
|
弹性计算 Linux 区块链
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
160 4
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)