用户空间程序有数据库服务ovsdb-server和守护进程ovs-vswitchd.kernel中是 datapath的内核模块,最上面的Contronller表示OpenFlow控制器,控制器与OVS进行通信是经由openflow协议。
https://blog.csdn.net/maijian/post/details/74332260
顾名思义,Bridge代表一个以太网交换机(switch),一个主机可以创建一个或者多个的 Bridge,它的功能就是根据一定规则,把从某一个端口收到的数据发送到一个或者多个端口中。
添加一个网桥br0
ovs-vsctl add-br br0
端口(port): 这个概念与物理交换机的端口相似,是在OVS Bridge上创建的一个虚拟端口,每个port都有自己的Bridge.值得注意的是,Port有下面几种类型:
1 Normal
可以把宿主OS上的网卡挂载到OVS上,此时OVS会生成同名的Port处理这块网卡发出的数据包。这种类型的port成为Normal.且不分配Ip地址,也就是说之前分配的地址无法访问。(虚拟机网卡tap***)
ovs-vsctl add-port br-ext eth1
#Bridge br-ext中出现Port "eth1"
2 internal
这个端口的作用就是自动创建一个同名接口(interface) 挂载到新建立的Port上。
ovs-vsctl add-br br0
ovs-vsctl add-port br0 p0 -- set Interface p0 type=internal
#查看网桥br0
ovs-vsctl show br0
Bridge "br0"
fail_mode: secure
Port "p0"
Interface "p0"
type: internal
Port "br0"
Interface "br0"
type: internal
可以看到有两个Port。当ovs创建一个新网桥时,默认会创建一个与网桥同名的Internal Port。在OVS中,只有”internal”类型的设备才支持配置IP地址信息,因此我们可以为br0接口配置一个IP地址,当然p0也可以配置IP地址
ip addr add 192.168.10.11/24 dev br0
ip link set br0 up
#添加默认路由
ip route add default via 192.168.10.1 dev br0
3 patch
当主机中有多个ovs网桥时,可以使用Patch Port把两个网桥连起来。Patch Port总是成对出现,分别连接在两个网桥上,从一个Patch Port收到的数据包会被转发到另一个Patch Port,类似于Linux系统中的veth。使用Patch连接的两个网桥跟一个网桥没什么区别,OpenStack Neutron中使用到了Patch Port。上面网桥br-ext中的Port phy-br-ext与br-int中的Port int-br-ext是一对Patch Port
演示:
ovs-vsctl add-br br0
ovs-vsctl add-br br1
ovs-vsctl \
-- add-port br0 patch0 -- set interface patch0 type=patch options:peer=patch1 \
-- add-port br1 patch1 -- set interface patch1 type=patch options:peer=patch0
#结果如下
#ovs-vsctl show
Bridge "br0"
Port "br0"
Interface "br0"
type: internal
Port "patch0"
Interface "patch0"
type: patch
options: {peer="patch1"}
Bridge "br1"
Port "br1"
Interface "br1"
type: internal
Port "patch1"
Interface "patch1"
type: patch
options: {peer="patch0"}
还有一个Tunnel,以后再说了。
https://www.usenix.org/system/files/conference/nsdi15/nsdi15-paper-pfaff.pdf
[how to do reasch at under?]http://www.ece.rutgers.edu/~pompili/index_file/extra/HowToDoResearch_ANRG_WP02001.pdf
有关在ovs下的Qos命令 http://www.programmersought.com/article/294415472/
docker安装的话请参考这篇文章article
Docker binds a Unix socket, but it need rootuser also.If you do not want use root, there is the best way to do it with creating dockeruser group add user into it.When the Docker daemon starts, it create a Unix socket accessible by members of the docker group.
After installing the Docker, you can verfy it with below:
yubo@debian:~/git/yuzibo.github.io/_posts$ sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Already exists
Digest: sha256:5f179596a7335398b805f036f7e8561b6f0e32cd30a32f5e19d17a3cda6cc33d
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
sudo groupadd docker
sudo usermod -aG docker $USER
你得退出当前的登录界面才可以,再次重新登录。
docker run hello-world
Enable it with systemd:
sudo systemctl enable docker
Given a non-empty array of digits representing a non-negative integer, plus one to the integer.
The digits are stored such that the most significant digit is at the head of the list, and each element in the array contain a single digit.
You may assume the integer does not contain any leading zero, except the number 0 itself. Example 1:
Input: [1,2,3]
Output: [1,2,4]
Explanation: The array represents the integer 123. 通过这道题目,自己对c语言的动态内存分配的理解更加清晰一点了。 首先一点就是,将这样数目大的数组使用整型数组的方式表示,这样对int的使用范围提升了一大截。
for(i = digitsSize-1; i >= 0; i--){
//printf("in func num is %d and i is %d\t", digits[i],i);
if(++digits[i] < 10)
return digits;
digits[i] %= 10;
}
这样就在int *a里面完成了最后一位的加1操作。
接下来的一个操作就是realloc的使用,在c中,我们使用malloc的场合是比较多的啦,那么,怎么使用realloc方法呢?或者说,没什么使用这一个函数? 假设[9,9,9,9],最后一位加1, 不就是变成了[1,0,0,0,0]吗,我们非常清楚的看见这个数组(尤其注意的一点是,realloc/malloc/calloc函数的产生作用的指针只能是指针,任何数组类型的都会导致出错)的的位数明显加1,这个应该怎么处理?
digits = realloc(digits, sizeof(int) * ++(*returnSize));
digits[*returnSize - 1]= 0;
digits[0] = 1;
其中,以上面的例子为说明,*returnSize的大小在之前已经赋予了4,经过自加1之后,我们看到,realloc实际上是申请的最终的大小(5),也即你最终使用指针的那个大小。最终的代码为:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int* plusOne(int* digits, int digitsSize, int* returnSize){
int i;
if(!digits)
return NULL;
*returnSize = digitsSize;
for(i = digitsSize-1; i >= 0; i--){
//printf("in func num is %d and i is %d\t", digits[i],i);
if(++digits[i] < 10)
return digits;
digits[i] %= 10;
}
digits = realloc(digits, sizeof(int) * ++(*returnSize));
digits[*returnSize - 1]= 0;
digits[0] = 1;
//*returnSize += 1;
return digits;
}
int main()
{
//int a[4] = {9,9,9,9};
int *b =(int *)malloc(sizeof(int));
int c;
int *a = (int *)malloc(sizeof(int) * 10);
*a = 9, *(a + 1) = 9, *(a + 2) = 9, *(a + 3) = 9;
b = plusOne(a, 4, &c);
int i;
printf("the returnSize is %d\n",c);
for(i = 0; i < c; i++)
printf("%d\t", b[i]);
free(b);
}
这里将主函数写在这里,会更加清楚realloc的使用范围。 realloc-old-size
Example 1:
Given nums = [3,2,2,3], val = 3,
Your function should return length = 2, with the first two elements of nums being 2.
It doesn't matter what you leave beyond the returned length.
Example 2:
Given nums = [0,1,2,2,3,0,4,2], val = 2,
Your function should return length = 5, with the first five elements of nums containing 0, 1, 3, 0, and 4.
使用一个新的索引指向插入的位置。这里值得注意的一个地方在于,按照题目的要求,如果不开辟新的存储空间,那么,本人能想到(也是leetcode提供的)方法就是,那这个数组以引用的形式传递过去,结果返回这个删除重复元素的数组的有效个数。
nt removeElement(int* nums, int numsSize, int val) {
int i, index = 0;// 作用是标记上次移动的位置
for(i = 0; i < numsSize; i++){
if(nums[i] != val){
nums[index++] = nums[i];
}
}
return index;
}
实际上leetcode 已经说了这个提示:
// nums is passed in by reference. (i.e., without making a copy)
int len = removeElement(nums, val);
// any modification to nums in your function would be known by the caller.
// using the length returned by your function, it prints the first len elements.
for (int i = 0; i < len; i++) {
print(nums[i]);
}
那么,这个方法能不能在工程中使用呢,现在不得知。
# 38 count and say
使用两个数组,变量的使用也很讲究。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *countAndSay(int n)
{
if (n == 1)
return "1";
char *res = (char *)malloc(sizeof(char) * 2);
res[0] = '1';
res[1] = 0;
int i, len;
for(i = 2; i<= n; ++i){
len = strlen(res);
char *tmp = malloc(len * 3);
memset(tmp, 0, len * 3);
int j, idx,count = 1;
//printf("here len is %d\n", len);
for(j = 0,idx = 1; idx < len; idx++){
if(res[idx] == res[idx-1]){
count++;
//break;
}
else{
tmp[j++] = '0' + count;
tmp[j++] = res[idx-1];
count = 1;
}
}
tmp[j++] = '0' + count;
tmp[j++] = res[len-1];
free(res);
res = tmp;
}
return res;
}
int main()
{
int i;
char *s = countAndSay(4);
printf("%s\n", s);
free(s);
}
# 53 Maximum Subarray
Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
上面就是这个题目的简单示意图.
这个题目有三种解法,这里只是简单地介绍其中的几种,O(N^2)、O(NlgN)和O(N) 的算法。
简单来说就是设置两个指针,分别指定两个指针为子序列的左侧。比如,序列,[1,2,3],都指向1,然后依次累加,注意这个时候就可以知道他们的最大值(累加时);第二趟从2开始也可以知道其中的最大值,分别记录下来。
int maxSubArray(int* nums, int numsSize){
int i,j,k,max_sum = nums[0],this_sum,start = 0, end = numsSize;
for(i = 0; i < numsSize; i++){
this_sum = 0;
for(j = i; j < numsSize; j++){
this_sum += nums[j];
if (this_sum > max_sum){
max_sum = this_sum;
start = i;
end = j;
}
}
}
printf("the start is %d\t, the end is %d", start, end);
return max_sum;
}
这个方案把子序列的起始点和重点全部打印出来了。
分治算法的使用。
根据题目的特点,我们判断每一个节点时的和是否大于0,是的话,就以当前节点相加,不是的话,就以当前节点为最大值。可惜这个算法在leetcode上只为28%
int maxSubArray(int* nums, int numsSize){
int i,j,k,max_sum = nums[0],this_sum = nums[0],start = i, end = numsSize;
for(i = 1; i < numsSize; i++){
if(this_sum <= 0)
this_sum = nums[i];
else
this_sum += nums[i];
if(max_sum < this_sum)
max_sum = this_sum;
}
// printf("the start is %d\t, the end is %d", start, end);
return max_sum;
}
都这么厉害吗 ^_^!!
说来惭愧,认识c语言这么久,这是第一次对c的动态分配内存方式有了一个直观的认识。
以小端机器为例:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -->high address
| |==> 命令行参数以及环境变量
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| stack |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
V
^
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| heap |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| uninitialized dada(bss) | initialized to zero
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ by exec
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| initialized dada |----read from program file
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ by exec
/
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+/
| text |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ low address
我们经常定义的字符串也许就是放在这里,这里我用了也许,因为我还没有实验出来,如果证实了,自然不会用这个词了。
这个位置也叫数据段,主要存放全局变量和static关键词变量。注意,这里可以分为可读写data或者只读只写data段注意,这里可以分为可读写data或者只读只写data段
static int i = 0;
// 或者
global int j = 0;
will be stored here.
也叫bss段(block started by symbol),
这时这篇文章主要介绍的一个知识点
首先借助一个测试程序进行验证:
#include <stdio.h>
int main()
{
return 0;
}
进行编译后查看文件各段的大小。size命令就是查看文件中section的大小,具体可以查看man手册
yubo-2@debian:~/test$ gcc -g memory-layout.c -o memory-layout
yubo-2@debian:~/test$ size memory-layout
text data bss dec hex filename
1521 544 8 2073 819 memory-layout
之所以各段这么大,是因为这个可执行文件还具有其他的一些工作也被加载到这个文件中了,我们使用相对数量来反应 这个变化。 我们再看一下汇编文件:
yubo-2@debian:~/test$ cat memory-layout.s
.file "memory-layout.c"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp //将前面的程序地址压入栈
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp //将这个函数的地址压入
.cfi_def_cfa_register 6
movl $0, %eax // 传递返回值
popq %rbp //返回上面的程序
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
...
#include <stdio.h>
int global;
int main()
{
return 0;
}
查看size文件变化:
yubo-2@debian:~/test$ size memory-layout
text data bss dec hex filename
1521 544 8 2073 819 memory-layout
.file "memory-layout.c"
.comm global,4,4 //差别就在这里
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
...
对,就是这个样子,在我的机器上,没有初始化的变量或者初始化为0的全局变量以及静态变量不会增加bss的大小,相反,如果你初始化为非0的 数据,则data段会增加。
#include <stdio.h>
int test = 3;
int main(void)
{
static int i = 3;
return 0;
}
看一下size:
yubo-2@debian:~/test$ size memory-layout
text data bss dec hex filename
1521 552 8 2081 821 memory-layout
data增加了两个(int)的大小。
stack和heap在程序运行时进行分配空间,后面三个由编译器决定其空间。啊哈,所以ali 的大神面试我的那个问题就有眉目了,定义多个 变量会影响文件的大小 汗.
数组相比大家都熟悉了,这个方式有一个特点,就是数组的大小在编译时就确定了,其存放在
下面是动态分配内存使用的方法分配空间。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, num;
float *data;
printf("Enter total number of elements(1 to 100): ");
scanf("%d", &num);
// Allocates the memory for 'num' elements.
data = (float*) calloc(num, sizeof(float));
if(data == NULL)
{
printf("Error!!! memory not allocated.");
exit(0);
}
printf("\n");
// Stores the number entered by the user.
for(i = 0; i < num; ++i)
{
printf("Enter Number %d: ", i + 1);
scanf("%f", data + i);
}
// Loop to store largest number at address data
for(i = 1; i < num; ++i)
{
// Change < to > if you want to find the smallest number
if(*data < *(data + i))
*data = *(data + i);
}
printf("Largest element = %.2f", *data);
return 0;
}
https://www.geeksforgeeks.org/memory-layout-of-c-program/
https://www.programiz.com/c-programming/examples/dynamic-memory-allocation-largest
csdn 这篇博客还是非常牛b的,有时间把上述场景复现一遍,我说一下我的解决方案。
首先找到你要 checkout的那个分支,如果是远程的话,自己先新建一个分支:
git checkout -b new_branch(or test, so this is the same name) <name of remote>/test
这个时候HEAD就在新的分支上去了。
这篇文章简单介绍下kernel中汇编的一些小的基础知识。
4
0x1234 0x1234 - 正确
0x1234 0x1234 - 正确
movb 0x12, %ah
movw $0x123, %ax
movl (%ebx), %edx
movl %eax, %edx
movl %eax, %edx
选a.
32 位x86 CPU中,cs:eip指向要执行的指令地址,所以想执行0x123处的代码,我们可以通过mov $0x123, %eip指令来跳转 错误。%eip不能直接寻址,必须经过寄存器传值。
与下面两条指令等价的指令是(): pushl %ebp movl %esp, %ebp
(enter)