linux

后台进程读/写控制台触发SIGTTIN/SIGTTOU信号量

  Unix环境下,当一个进程以后台形式启动,但尝试去读写控制台终端时,将会触发SIGTTIN(读)和SIGTTOU(写)信号量,接着,进程将会暂停(linux默认情况下),read/write将会返回错误。这个时候,shell将会发送通知给用户,提醒用户切换此进程为前台进程,以便继续执行。由后台切换至前台的方式是fg命令,前台转为后台则为CTRL+Z快捷键。   那么问题来了,如何才能在不把进程切换至前台的情况下,读写控制器不会被暂停?答案:只要忽略SIGTTIN和SIGTTOU信号量即可:signal(SIGTTOU, SIG_IGN)。   stty stop/-stop命令是用于设置收到SIGTTOU信号量后是否执行暂停,因为有些系统的默认行为不一致,比如mac是默认忽略,而linux是默认启用。stty -a可以查看当前…

Read more

Pid file和进程副本

  在守护进程(daemon)中,经常需要向/var/run/中写入pid文件:xxx.pid,该文件里的内容是xxx进程的进程号。 1.如何防止启动多个副本   为了防止启动一个进程的多个副本,需要在写的时候申请文件锁,一个进程一旦申请文件锁后,会一直锁住该pid文件,直到进程退出,这样也就达到了只启动一个副本的目的。   实例代码如下: const string LOCKFILE = "/var/run/agent.pid"; const mode_t LOCKMOD = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); int lockfile (int fd) { struct flock fl; fl.l_type = F_WRLCK; fl.l_sta…

Read more

Linux页高速缓存和页回写

  页高速缓存(cache)是Linux内核实现磁盘缓存的机制。磁盘高速缓存之所以重要的原因有二:1.访问磁盘的速度要远远低于访问内存的速度;2.数据一旦被访问,根据临时局部原理,它将很有可能在短时间内再次被访问到。 1.缓存手段   页高速缓存是由内存中的物理页面组成的,其内容对应磁盘上的物理块。页高速缓存大小能动态调整--它可以通过占用空闲内存以扩张大小,也可以自我收缩以缓解内存压力。注意,系统不一定要将整个文件都缓存,而只是缓存部分。 1.1写缓存   包括以下三种: 不缓存。直接写磁盘。 写透缓存。写操作自动更新内存缓存,同时也更新磁盘文件。 回写。程序执行写操作直接写到缓存中,后端存储不会立刻更新,而是将页高速缓存中被写入的页面标记为『脏』页,并被加入到脏页链表。然后由一个进程周期性将脏页链表中的页写回到磁盘。…

Read more

Linux进程地址空间

  对一个进程而言,它好像都可以访问整个系统的所有物理内存。即使单独一个进程,它拥有的地址空间也远远大于系统物理内存。 1.地址空间   每个进程都有一个32位或者64位的平坦(flat)地址空间,空间具体大小取决于体系结构,平坦指的是地址空间范围是一个独立的连续区间。一些操作系统提供了段地址空间,这种空间并非是一个独立的线性区域,而是被分段的,但现代采用虚拟内存的操作系统通常都是使用平坦地址空间而不是分段式的内存模式。通常情况下,每个进程都有唯一的这种平坦地址空间。一个进程的地址空间与另一个进程的地址空间即使有相同的内存地址,实际上彼此不相干。我们称这样的进程为线程。   尽管一个进程可以寻址4GB的虚拟内存,但这并不代表它就有权访问所有的虚拟地址。我们把可被访问的合法地址空间称为内存区域。通过内核,进程可以给自己的地址空间动态…

Read more

Linux虚拟文件系统

  通过虚拟文件系统(VFS),程序可以利用标准的Unix系统调用对不同的文件系统,甚至不同介质上的文件系统进行读写操作,如下图所示:使用cp(1)命令从ext3文件系统格式的硬盘拷贝数据到ext2文件系统格式的可移动磁盘上。两种不同的文件系统,两种不同的介质,连接到同一个VFS上。 1.文件系统抽象层   vfs可以使得用户可以直接使用open(),read(),write()这样的系统调用而无须考虑具体文件系统和实际物理介质。vfs把各种不同的文件系统抽象后采用统一的方式进行操作。而之所以可以使用这种通用接口对所有类型的文件系统进行操作,是因为内核在它的底层文件系统接口上建立了一个抽象层。该抽象层使Linux能够支持各种文件系统,即便是它们在功能和行为上存在很大差异。下图展示了一次用户控件的write()调用具体触发的流程。 2.Unix文件系统…

Read more

Linux内存管理

  在内核中分配内存空间不像在其他地方分配内存这么容易,主要原因是空间受限。内核与用户空间不同,不支持这种简单便捷的内存分配方式。 1.页   内核把物理页作为内存管理的基本单位。尽管处理器的最小可寻址单位是字,但内存管理单元(MMU)通常以页为单位进行处理,大多数32位体系结构支持4KB的页,64位为8KB。内核用struct page结构体表示系统中的每个物理页。 struct page { unsigned long flags; //页状态,标识是否为脏页,是否锁定在内存等等。一共有32位标识 atomic_t _count; //该物理页的引用次数 atomic_t _mapcount; unsigned long private; struct address_space *mapping;…

Read more

Linux bridge学习

  Linux bridge是Linux内核中虚拟网桥的一个实现,它与OpenvSwitch都实现交换机功能,但比后者简单一些,只实现了最简单的二层功能,而没有ovs下诸如QoS,OpenFlow,netconf等等复杂的功能。本文主要参考《深入理解Linux网络技术内幕》,更像一个读书笔记性质的小结。   虚拟网桥是定义在真实设备之上的一个抽象设备,当该真实设备发生状态变化,则Linux bridge会受到影响。netdevice通知链向内核注册br_device_event回调函数,任何真实设备的变动会触发该回调函数。   下图是在有无网桥情况下收发包的示意图。在设备上传输数据是通过dev_queue_xmit执行的,它会调用设备驱动函数hard_start_xmit进行发包,中间有一些查找发包的过程。dev_queue_xm…

Read more

源码查看神器OpenGrok

  MAC/Linux下,vim+各种插件对于大规模代码还是不行,网上找了个神器OpenGrok可以查看。   2017_08_16 Update:文章末尾提到的insight.io是一款更加优秀的源码阅读工具。 1. 首先安装java环境:jre,jdk。 2. 安装tomacat brew install tomcat 3. 安装ctags brew install ctags 4. 下载OpenGrok wget -O - http://java.net/projects/opengrok/downloads/download/opengrok-0.12.1.tar.gz | tar xvz 5. 在tomcat上部署 OPENGROK_TOMCAT_BASE=/usr/local/Cellar/tomcat/8.0.17/…

Read more

Quagga运行多个ospfd进程

  最近需要用Quagga连接SDN controller运行路由协议,代替TOR跑ospf,其实这个在一个TOR的状态下是一点问题都没有的,参考一下官网文档就能很快搞定。但问题的关键是我有两个TOR,然后问题就出现了,如何在Quagga上运行两个ospfd进程?方法如下: 找另外一台机器,无论是本地启动虚拟机也好,或者找一台物理机器也好,运行两个Quagga,然后做RPC通信。 做Namespace隔离,隔离出两个ospfd进程   方法一比较曲折,这对于两台TOR来说或许是个缓兵之计,但当我们以后TOR数量增加的时候这个缺陷就暴露了,明显我们不可能为每台TOR搞个物理机器或者虚拟机。然后想着想着想到了docker,搞个轻量级虚拟机;再然后我仔细一想,直接自己做隔离好了。想法不错,动手开搞,调查了好久发现这个方法也太困难了,关于linux na…

Read more

tun/tap运行机制

  最近需要连接Quagga和SDN Controller,由于Quagga原因,目前没办法直接在两者之间建立连接,所以只能曲线救国,采用tun/tap搞个虚拟网卡中转一下。本文主要介绍以下tun/tap的机制,关于具体连接部分将在以后进行介绍。   tun和tap的区别在于tun是三层设备,用于ip转发,无法与物理网卡做 bridge,但是可以通过三层交换(如 ip_forward)与物理网卡连通;tap是二层设备,用于mac转发。   以下几个图来自kghost的博客。   首先是正常网卡接收报文是从物理链路接收的:   而虚拟网卡(tun/tap)是从用户态接收数据,在用户态和协议栈之间进行中转数据。数据从用户态读进来,穿透/dev/net/tun字符设备抵达内核,然后交给虚拟网卡,虚…

Read more

mininet与namespace

  前一阵发现一个问题,就是用mininet起的主机的namespace用ip netns查看不到,一直感觉很奇怪,因为根据mininet官网给出的描述,起创建的switch,host还有自带的controller都是位于namespace下的,其中switch和自带controller都是位于root namespace下,不同host是位于不同的host下面,但是为啥子用ip netns就看不到,明明ip netns就是查看namespace的。今天有时间,上网查了一下,终于知道以前了解的namespace只是冰山一角。本文只给出概括说明,具体不同namespace的详细用法查看文章底部的链接。   总得概括来说其实就是一句话:ip netns add创建的namespace是带name的,而mininet创建的namespace是nameles…

Read more

ovs 2.3 流表匹配过程

  艾妈,终于跟进新版本流表匹配了。忧伤的故事是新版本内核匹配修改了好多,下放了部分wildcard matching到内核。源码看懂是没太大问题,逻辑还需要好好梳理一下。 1.datapatch内核流表匹配   datapath收到数据包的具体流程如下,艾妈,画得太丑,大家见谅: 1. neifreceive_skb是网卡收到包的函数,将会递送给netdev_frame_hook 2. netdev_frame_hook这个函数是vport初始化使注册的钩子函数,初始化vport流程(初始化vport => ovs_netdev_vport_ops => netdev_rx_handler_register)。它主要调用了两个函数: (1) vport = ovs_netdev_get_vport(skb->dev); //获取对应d…

Read more

linux使用nc命令传输文件

  目的主机的22端口不能使用,于是scp也不能用,想要传文件可以使用nc命令: 目的主机:nc -l 8765 > outFilename 源主机:nc 目的主机ip 目的主机nc端口 < inFilename 其中目的主机端口开大一点,别占用系统端口就好了。   nc还有很多很强大的功能,比如聊天,扫描端口等等,具体可以参考man。 参考 http://www.linuxso.com/command/nc.html…

Read more

ovs中流表在内核空间与用户空间的匹配过程

  一直对ovs中facet和subfacet概念搞不清楚,今天仔细查了网上,关于这个的解释信息好少,以下这个是mail list里面的回答,感觉挺正确了: As I understand, there are two kinds of flow in OVS. One is in the user space, e.g. vswitchd, where flow key can include some wildcards to match, while the other lies in kernel space, e.g. openvswitch.ko, where the flow key can never have wildcard. If no wildcard in user space flow (a.k.a facet), the flow from…

Read more

ovs datapath笔记

  这几天在学习ovs的源码,现在来做个datapath的笔记。事先声明,本文的内容摘自博客,源码,视频以及自己的总结等,具体参考文献已经在文章末尾给出,主要参考为Baohua Yang的OpenvSwitch 代码分析。 0.模块介绍   datapath为ovs内核模块,负责执行数据交换,也就是把从接收端口收到的数据包在流表中进行匹配,并执行匹配到的动作。   一个datapath可以对应多个vport,一个vport类似物理交换机的端口概念。一个datapth关联一个flow table,一个flow table包含多个条目,每个条目包括两个内容:一个match/key和一个action,一个match/key可以从包中获取,对应一个action处理行为,最常见的action是在不同flow中进行转发。下图所示的是1…

Read more

shell中设置static变量

  我有一个代码,需要在并行机上跑,但是由于需要测试不同的参数,问题就很纠结。一开始我把这些参数写到文件,然后提交多次脚本,脚本中设置从文件中获取变量。结果发现提交时每个脚本总是提交最后一次的参数,因为提交时任务不确定,而写入文件的变量会发生覆盖,导致脚本开始跑的时候只有最后一次参数生效。   说的有点绕口,反正,如果需要在文件中设置static变量或者全局变量就用export到环境变量就可以了: a=1 $a=$(($a+1)) export a…

Read more

Linux网络内核数据结构之sk_buff

  sk_buff是Linux网络内核中最重要的数据结构之一。所有网络分层(MAC或L2分层上的另一种链路层协议,L3的IP,L4的TCP或UDP)都会使用这个结构来存储其报头,有关用户数据的信息,以及用来协调其工作的其他内部信息。当该结构从一个分层传到另一个分层时,其不同的字段会随之发生改变。在不同层数据传递时,通过附加报头的形式,减少了拷贝带来的开销。   内核把所有sk_buff结构链成一个双向链表,并添加了一个头元素,该头元素的结构是sk_buff_head: struct sk_buff_head {   struct sk_buff *next; 指向后继结点   struct sk_buff *prev; 指向前驱结点   __u32 qlen; 表中元素的数…

Read more

Netfilter/iptables框架总结

  今天,又把Netfilter回顾了一遍,发现经常容易遗忘,就写一篇博客总结一下。其实说起来总结,也都是参考网上大神的文献,文献已经在文章的末尾给出。 1. 概述   首先,说一下这两个是什么东西吧。netfilter是Linux内核中用于包过滤的框架,而iptables是在其之上设置的软件。它有五个钩子(Hook)去控制包的流动,总的来说就是我们可以在这5个钩子上设置过滤规则去控制包的流入/流出/转发等: INPUT:进入本机 OUTPUT:本机输出 FORWARD:转发 PREROUTING:输入控制 POSTROUTING:输出控制   其次,介绍一下这个框架到底能做些什么东西: 建立一个基于有状态和无状态的包过滤规则的因特网防火墙。 部署高度可用的有状态和无状态防火墙集群。 当公网ip不够用时,可以进行ip伪装,…

Read more

Linux内核同步方法

1. 原子操作   内核提供了两组原子操作接口--一组针对整数进行操作,另一组针对单独的位进行操作。 1.1 原子整数操作   针对整数的原子操作智能对atomic_t类型的数据进行处理。在这里之所以引入了一个特殊数据类型,而没有直接用C语言的int,主要处于以下原因: 让原子函数只接收atomic_t类型的操作数,可以确保原子操作只与这种特殊类型数据一起使用。同时,也保证了该类型的数据不会被传递给任何非原子函数。 使用atomic_t类型确保编译器不对相应的值进行访问优化--这点使得原子操作最终接收到正确的内存地址,而不是别名。 在不同体系结构上实现原子操作的时候,使用atomic_t可以屏蔽其间的差异。   atomic_t是32位数,后来引入了64位的atomic64_t。下图是原子整数操作函数表: 1.2…

Read more

中断之后下半部和推后执行的工作

  在前面所说的中断处理程序,由于本身存在一些局限,所以它智能完成整个中断处理流程的上半部。这些局限包括: 中断处理程序以异步方式执行,并且它有可能会打断其他重要代码(甚至包括其他中断处理程序)的执行。因此,为了避免被打断的代码停止时间过长,中断处理程序应该执行得越快越好。 如果当前有一个中断处理程序正在执行,在最好的情况下,与该中断同级的其他中断会被屏蔽,在最坏的情况下,当前处理器上所有其他中断都会被屏蔽。因为禁止中断后硬件与OS无法通信,因此,中断处理程序执行得越快越好。 由于中断处理程序往往需要对硬件进行操作,所以它们通常有很高的时限要求。 中断处理程序不在进程上下文中运行,所以它们不能阻塞。 1.下半部   下半部的任务就是执行与中断处理密切相关但中断处理程序本身不执行的工作。在理想的情况下,最好是中断处理程序将所有工作都交给下半…

Read more