一、技术背景因业务需求需要基于sipserver实现音视频对讲,开源代码linephone即可实现。开源库地址:https://github.com/topics/linphone二、基于安卓客户端实现添加build.gradle依赖repositories { maven { // Replace snapshots by releases for releases ! url "http://linphone.org/releases/mav.

文件:url80.ctfile.com/f/25127180-734962452-627875?p=551685 (访问密码: 551685)


docker 的工作方式
当我们的程序运行起来的时候,在计算机中的表现就是一个个的进程,一个 docker 容器中可以跑各种程序,容器技术的核心功能,就是通过约束和修改进程的动态表现,从而为其创造出一个“边界”。

Docker 容器启动的进程还是在宿主机中运行的,和宿主机中其他运行的进程是没有区别的,只是 docker 容器会给这些进程,添加各种各样的 Namespace 参数,使这些进程和宿主机中的其它进程隔离开来,感知不到有其它进程的存在。

对于 Docker 等大多数 Linux 容器来说,Cgroups 技术是用来进行资源限制,而 Namespace 技术用来做隔离作用。

容器是一种特殊的进程:

docker 容器在创建进程时,指定了这个进程所需要启用的一组 Namespace 参数。这样,容器就只能“看”到当前 Namespace 所限定的资源、文件、设备、状态,或者配置。而对于宿主机以及其他不相关的程序,它就完全看不到了。

容器中启动的进程,还是在宿主机中运行的,只是 docker 容器会给这些进程,添加各种各样的 Namespace 参数,使这些进程和宿主机中的其它进程隔离开来,感知不到有其它进程的存在。

下面来看下 docker 容器中,Namespace 和 Cgroups 的具体作用

Namespace
Namespace 是 Linux 中隔离内核资源的方式,通过 Namespace 可以这些进程只能看到自己 Namespace 的相关资源,这样和其它 Namespace 的进程起到了隔离的作用。

Linux namespaces 是对全局系统资源的一种封装隔离,使得处于不同 namespace 的进程拥有独立的全局系统资源,改变一个 namespace 中的系统资源只会影响当前 namespace 里的进程,对其他 namespace 中的进程没有影响。

docker 容器的实现正是用到了 Namespace 的隔离,docker 容器通过启动的时候给进程添加 Namespace 参数,这样,容器就只能“看”到当前 Namespace 所限定的资源、文件、设备、状态,或者配置。而对于宿主机以及其他不相关的程序,它就完全看不到了。

容器对比虚拟机
虚拟机

使用虚拟机,就需要使用 Hypervisor 来负责创建虚拟机,这个虚拟机是真实存在的,并且里面需要运行 Guest OS 才能执行用户的应用进程,这就不可避免会带来额外的资源消耗和占用。

虚拟机本身的运行就会占用一定的资源,同时虚拟机对宿主机文件的调用,就不可避免的需要经过虚拟化软件的连接和处理,这本身就是一层性能消耗,尤其对计算资源、网络和磁盘 I/O 的损耗非常大。

容器

容器化后的应用,还是宿主机上的一个普通的进程,不会存在虚拟化带来的性能损耗,同时容器使用的是 Namespace 进行隔离的,所以不需要单独的 Guest OS,这就使得容器额外的资源占用几乎可以忽略不计。

容器的缺点

基于 Linux Namespace 的隔离机制相比于虚拟化技术也有很多不足之处,其中最主要的问题就是:隔离得不彻底。

1、容器只是运行在宿主机中的一中特殊的进程,容器时间使用的还是同一个宿主机的操作系统内核;

尽管你可以在容器里通过 Mount Namespace 单独挂载其他不同版本的操作系统文件,比如 CentOS 或者 Ubuntu,但这并不能改变共享宿主机内核的事实。这意味着,如果你要在 Windows 宿主机上运行 Linux 容器,或者在低版本的 Linux 宿主机上运行高版本的 Linux 容器,都是行不通的。

2、在 Linux 内核中,有很多资源和对象是不能被 Namespace 化的,最典型的例子就是:时间;

如果容器中的程序使用了 settimeofday(2) 系统调用修改了时间,整个宿主机的时间都会被随之修改,所以容器中我们应该尽量避免这种操作。

3、容器共享宿主机内核,会给应用暴露出更大的攻击面。

在是生产环境中,不会把物理机中 Linux 的容器直接暴露在公网上。

Cgroups
docker 容器中的进程使用 Namespace 来进行隔离,使得这些在容器中运行的进程像是运行在一个独立的环境中一样。但是,被隔离的进程还是运行在宿主机中的,如果这些进程没有对资源进行限制,这些进程可能会占用很多的系统资源,影响到其他的进程。Docker 使用 Linux cgroups 来限制容器中的进程允许使用的系统资源。

Linux Cgroups 的全称是 Linux Control Group。它最主要的作用,就是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。

在 Linux 中,Cgroups 给用户暴露出来的操作接口是文件系统,即它以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下。

centos 7.2 下面的文件

mount -t cgroup

cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct,cpu)
cgroup on /sys/fs/cgroup/net_cls type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)

Linux Cgroups 的设计还是比较易用的,简单粗暴地理解呢,它就是一个子系统目录加上一组资源限制文件的组合。而对于 Docker 等 Linux 容器项目来说,它们只需要在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录),然后在启动容器进程之后,把这个进程的 PID 填写到对应控制组的 tasks 文件中就可以了。

总结下来就是,一个正在运行的 Docker 容器,其实就是一个启用了多个 Linux Namespace 的应用进程,而这个进程能够使用的资源量,则受 Cgroups 配置的限制。

容器看到的文件
Mount namespace
首先来了解下 Mount namespace

Mount namespace 为进程提供独立的文件系统视图。简单点说就是,mount namespace 用来隔离文件系统的挂载点,这样进程就只能看到自己的 mount namespace 中的文件系统挂载点。

进程的 mount namespace 中的挂载点信息可以在 /proc/[pid]/mounts、/proc/[pid]/mountinfo 和 /proc/[pid]/mountstats 这三个文件中找到。

每个 mount namespace 都有一份自己的挂载点列表。当我们使用 clone 函数或 unshare 函数并传入 CLONE_NEWNS 标志创建新的 mount namespace 时, 新 mount namespace 中的挂载点其实是从调用者所在的 mount namespace 中拷贝的。但是在新的 mount namespace 创建之后,这两个 mount namespace 及其挂载点就基本上没啥关系了(除了 shared subtree 的情况),两个 mount namespace 是相互隔离的。

Mount Namespace 修改的,是容器进程对文件系统“挂载点”的认知。但是,这也就意味着,只有在“挂载”这个操作发生之后,进程的视图才会被改变。而在此之前,新创建的容器会直接继承宿主机的各个挂载点。

这就是 Mount Namespace 跟其他 Namespace 的使用略有不同的地方:它对容器进程视图的改变,一定是伴随着挂载操作(mount)才能生效。

chroot
当一个容器被创建的时候,我们希望容器中进程看到的文件是一个独立的隔离环境,我们可以在容器进程重启之前挂载整个根目录 /,由于 Mount Namespace 的存在,这个挂载对宿主机不可见,所以容器进程就可以在里面随便折腾了。

在 Linux 中可以使用 chroot 来改变某进程的根目录。

来看下 chroot

chroot 主要是用来改换根目录的,在新设定的虚拟根目录中运行指定的命令或交互 Shell。一个运行在这个环境下,经由 chroot 设置根目录的程序,它不能够对这个指定根目录之外的文件进行访问动作,不能读取,也不能更改它的内容。

rootfs
为了让容器这个根目录看起来更’真实’,一般会在容器的根目录下面挂载一个完整的操作系统的文件系统,比如 Ubuntu16.04 的 ISO。这样,在容器启动之后,我们在容器里通过执行 ls / 查看根目录下的内容,就是 Ubuntu 16.04 的所有目录和文件。

这个挂载到容器根目录,用来给容器提供隔离后的执行环境的文件系统,称为为’容器镜像’,或者 rootfs(根文件系统)。

对于 Docker 来讲,最核心的原理就是为待创建的用户进程执行下面三个操作:

1、启用 Linux Namespace 配置;

2、设置指定的 Cgroups 参数;

3、切换进程的根目录(Change Root)。

第三步,进程根目录的切换,Docker 会优先使用 pivot_root 系统调用,如果系统不支持,才会使用 chroot。

rootfs 是一个操作系统包含的所有的文件、配置和目录,并不包括操作系统内核。同一宿主机中的容器都共享主机操作系统的内核。

正是由于 rootfs 的存在,容器中的一个很重要的特性才能实现,一致性。

因为 rootfs 中打包的不止是应用,还包括整个操作系统的文件和目录,应用和应用运行的所有依赖都会被封装在一起。这样无在任何一台机器中,只需要解压打包好的镜像,直接运行即可,因为镜像里面已经包含了应用运行的所有环境。

对于基础 rootfs 的制作,如果后续有更改的需求,一个很简单的操作就是,新 fork 一个然后修改,这样的缺点就是有很多碎片化的版本。

rootfs 的制作,也是支持增量的方式进行操作的,Docker 在镜像的设计中,引入了层(layer)的概念。也就是说,用户制作镜像的每一步操作,都会生成一个层,也就是一个增量 rootfs。

k8s
上面的读写层也称为容器层,下面的只读称为镜像层,所有的增删查改都只会作用在容器层,相同的文件上层会覆盖下层。

上面的读写层,在没有文件写入之前里面是空的,如果在容器里面做了修改,修改的内容就会以增量的方式出现在这个层中。

例如进行文件的修改,首先会从上到下查找有没有这个文件,找到,就复制到容器层中,修改,对容器来讲可以看到容器层中的这个文件,看不到镜像层中的这个文件。

进行删除的时候,也是在读写层做个标记,当这两个层被联合挂载之后,读写层的文件删除标记,会把容器中对应的文件“遮挡”起,对外面展示的效果就是该文件找不到了,被删除了。

最上面的可读可写层,就是专门存放修改后 rootfs 后产生的增量,修改,新增,删除产生的文件都会被记录到这里。这就是 rootfs 制作能支持增量模式的最主要实现。

这些增量的 rootfs,还可以使用 docker commit 和 push 指令,保存这个被修改过的可读写层,并上传到 Docker Hub 上。同时,原先只读层中的内容不会发生任何变化。当然这些读写层的增量 rootfs 在 commit 之后就会变成一个新的只读层了。

Volume(数据卷)
Volume 机制,允许将宿主机中指定的目录或者文件,挂载到容器中进行取和修改操作。

Volume 有两种挂载方式

$ docker run -v /test …
$ docker run -v /home:/test …
两种挂载方式实质上是一样的,第一种,没有指定挂载的宿主机的目录,docker 就会默认在宿主机上创建一个临时目录 /var/lib/docker/volumes/[VOLUME_ID]/_data,然后把它挂载到容器的 /test 目录上。

第二种,指定了宿主机中的目录,docker 就会把指定的宿主机中的 /home 目录挂载到容器的 /test 目录上。

docker 中使用了 rootfs 机制和 Mount Namespace,构建出了一个同宿主机完全隔离开的文件系统环境。对于 Volume 挂载又是如何实现的呢?这里来具体的分析下。

当容器进程被创建之后,尽管开启了Mount Namespace,但是在它执行 chroot(或者 pivot_root)之前,容器进程一直可以看到宿主机上的整个文件系统。

所以只需要在 rootfs 准备好之后,在执行 chroot 之前,把 Volume 指定的宿主机目录挂载到容器中的目录上即可,这样 Volume 挂载工作就完成了。

在执行这个挂载操作时,“容器进程”已经创建了,也就意味着此时 Mount Namespace 已经开启了。所以,这个挂载事件只在这个容器里可见。你在宿主机上,是看不见容器内部的这个挂载点的。这就保证了容器的隔离性不会被 Volume 打破。

这里用到了 Linux 的绑定挂载(bind mount)机制,它的主要作用就是,允许你将一个目录或者文件,而不是整个设备,挂载到一个指定的目录上。并且,这时你在该挂载点上进行的任何操作,只是发生在被挂载的目录或者文件上,而原挂载点的内容则会被隐藏起来且不受影响。

绑定挂载实际上是一个 inode 替换的过程,在 Linux 操作系统中,inode 可以理解为存放文件内容的"对象",dentry 也叫目录项,就是访问 inode 所有的指针。

音视频通话:​Linphone基于SIP协议的语音视频电话软件相关推荐

  1. Android音视频通话——Linphone开发笔记总结

    一.前言 前一段时间完成了基于linphone实现音视频通话的项目,踩了很多坑,特此总结记录. Linphone是一款开源基于SIP协议的语音视频电话软件,可移植到移动端Android.IOS.Win ...

  2. sip服务器开发--linphone是一款开源的基于sip协议的网络电话软件

    Android上最优秀的开源voip(网络电话)软件 目前知道有sipdroid.imsdroid.linphone,不知道还有没有其他的 还有MPhoneGG,使你使用Android手机也能拨打网络 ...

  3. VoIP通话-基于SIP协议的Asterisk(零)-Demo

    文章首发及后续更新:https://mwhls.top/4116.html,无图/无目录/格式错误/更多相关请至首发页查看. 新的更新内容请到mwhls.top查看. 欢迎提出任何疑问及批评,非常感谢 ...

  4. linux sipp 呼叫转移_基于SIP协议的呼叫转移功能实现.pdf

    ea句拣 却m川1归3 年第却卷材第 u E,sw部署跚跚跚. E囚le倪cb胁'O响叫ni沁cS缸ci. &τT.e优ch. /De盹ι 15 , 2013 基于 SIP 协议的呼叫转移功能 ...

  5. 基于SIP协议的视频通讯

    1.sip协议及其发展 sip(session initiation protocal)称为会话发起协议,是由ietf(internet engineering task force)组织于1999年 ...

  6. 【个人作品】推荐一个SIP客户端-软电话,基于SIP协议,语言C++,界面QT4 开源,asterisk,tribox测试成功

    推荐一个SIP客户端-软电话,基于SIP协议,语言C++,界面QT4 开源,asterisk,tribox测试成功 属于个人独创作品,欢迎使用测试,欢迎与作者联系,共同研究.如果大家喜欢将拿出源码. ...

  7. VoIP通话-基于SIP协议的Asterisk(一)-实现流程

    文章首发及后续更新:https://mwhls.top/4122.html,无图/无目录/格式错误/更多相关请至首发页查看. 新的更新内容请到mwhls.top查看. 欢迎提出任何疑问及批评,非常感谢 ...

  8. 基于SIP协议的IP电话系统设计与实现

    网络IP电话不仅具有成本低廉.网络资源利用率高等诸多优点,而且还可以进一步集成多媒体信息(包括语音.图像.数据等),以实现交互式的实时通信等,具有很大的发展潜力,且有逐渐取代传统PSTN电话的趋势,成 ...

  9. 基于SIP协议的IP电话增值业务实现技术

    基于SIP协议的IP电话增值业务实现技术 王瑜,乐正友 (清华大学电子工程系,北京 100084)    摘  要:讨论了SIP协议以及基于SIP协议的IP电话增值业务实现技术,并对SIP CGI.C ...

最新文章

  1. centos中mysql重置密码
  2. Seaborn在图像内自定义图例(legend)位置实战
  3. Kafka解惑之Old Producer(4)——Case Analysis
  4. 硬盘突然提示没有初始化_测试流程_507283-001 硬盘 HP SAS
  5. 使用 Spring Validation 优雅地进行参数校验
  6. Redis如何高效实现点赞、取消点赞功能
  7. boot客户管理系统源码_「计算机毕设」基于SpringBoot开发的仓库管理系统
  8. mybatis mysql net教程_MyBatis 教程
  9. 高并发大流量解决方案
  10. 淘宝评论API接口,item_review-获得淘宝商品评论API接口接入说明
  11. 输入一个字符,将大写字母换小写,小写变大写
  12. 攻防世界pwn高手进阶(持续更新)
  13. ERROR 1366(HY000)报错解决方法
  14. 一起学习C语言:C语言数据类型(二)
  15. 李飞飞:我怎样走上AI研究之路
  16. 使用python3完成英文词频统计
  17. 一个金融网站的SEO优化技巧案例
  18. html中奇数偶数判断,js中判断奇数或偶数
  19. 尝试探索3G通信网络
  20. Kong API网关使用笔记

热门文章

  1. hlsl函数 ddx ddy
  2. iPhone清理工具:4Easysoft iPhone Cleaner for Mac
  3. 求三个正整数的最大公约数和最小公倍数
  4. arnold降噪denoise官方教程
  5. Android 直播RTMP流
  6. Redis命令之集合(无序)
  7. 个人免签码支付源码+监控APP【野马资源网】
  8. 什么是你最关键的人脉
  9. Linux C/C++开发的难度到底在哪?大厂岗位要求
  10. 如何关闭WPS文字的选项卡显示方式?如何实现多窗口显示?