Linux虚拟内存和物理内存精华【美】
原文地址:
《Playing with Virtual Memory》
http://www.snailinaturtleneck.com/blog/2011/08/30/playing-with-virtual-memory/
扩展阅读:
《Understanding Memory》
http://www.ualberta.ca/CNS/RESEARCH/LinuxClusters/mem.html
《Understanding Virtual Memory》
http://www.redhat.com/magazine/001nov04/features/vm/
《MongoDB与内存》
http://huoding.com/2011/08/19/107
怎么玩转虚拟内存
当你运行一个进程,它需要一些内存来存储:堆,栈,使用的其他库。Linux为你的进程提供和清理内存像一个认真的管家。你可以(一般应该)只是让Linux做它自己的事情,但是知道发生了什么是一个很好的主意。
我想一个简单的方法去搞懂看看发生什么是使用pmap命令。pmap告诉你一个给定进程的内存信息。
例如,让我们看一个非常简单的C程序,打印出其自身的进程ID(PID),并暂停:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
printf("run `pmap %d`\n", getpid());
pause();
}
保存为mem_munch.c。现在编译并运行它:
# gcc mem_munch.c -o mem_munch # ./mem_munch run `pmap 25681`
你得到的PID可能会与我的(25681)不同。
在这一点上,该方案将“挂起”。这是因为暂停函数pause(),这正是我们想要的。现在,在我们空闲的时候可以看看关于这个进程的内存。
开启一个新的shell并运行PMAP,用下面的一个mem_munch更换PID:
# pmap 25681
25681: ./mem_munch
0000000000400000 4K r-x-- /home/user/mem_munch
0000000000600000 4K r---- /home/user/mem_munch
0000000000601000 4K rw--- /home/user/mem_munch
00007fcf5af88000 1576K r-x-- /lib/x86_64-linux-gnu/libc-2.13.so
00007fcf5b112000 2044K ----- /lib/x86_64-linux-gnu/libc-2.13.so
00007fcf5b311000 16K r---- /lib/x86_64-linux-gnu/libc-2.13.so
00007fcf5b315000 4K rw--- /lib/x86_64-linux-gnu/libc-2.13.so
00007fcf5b316000 24K rw--- [ anon ]
00007fcf5b31c000 132K r-x-- /lib/x86_64-linux-gnu/ld-2.13.so
00007fcf5b512000 12K rw--- [ anon ]
00007fcf5b539000 12K rw--- [ anon ]
00007fcf5b53c000 4K r---- /lib/x86_64-linux-gnu/ld-2.13.so
00007fcf5b53d000 8K rw--- /lib/x86_64-linux-gnu/ld-2.13.so
00007fff7efd8000 132K rw--- [ stack ]
00007fff7efff000 4K r-x-- [ anon ]
ffffffffff600000 4K r-x-- [ anon ]
total 3984K
未完,时间不够下次再写了,贴原文吧。
=========================================
Playing with Virtual Memory
When you run a process, it needs some memory to store things: its heap, its stack, and any libraries it’s using. Linux provides and cleans up memory for your process like an extremely conscientious butler. You can (and generally should) just let Linux do its thing, but it’s a good idea to understand the basics of what’s going on.
One easy way (I think) to understand this stuff is to actually look at what’s going on using the pmap command. pmap shows you memory information for a given process.
For example, let’s take a really simple C program that prints its own process id (PID) and pauses:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
printf("run `pmap %d`\n", getpid());
pause();
}
$ gcc mem_munch.c -o mem_munch $ ./mem_munch run `pmap 25681`
The PID you get will probably be different than mine (25681).
At this point, the program will “hang.” This is because of the pause() function, and it’s exactly what we want. Now we can look at the memory for this process at our leisure.
Open up a new shell and run pmap, replacing the PID below with the one mem_munch gave you:
$ pmap 25681 25681: ./mem_munch 0000000000400000 4K r-x-- /home/user/mem_munch 0000000000600000 4K r---- /home/user/mem_munch 0000000000601000 4K rw--- /home/user/mem_munch 00007fcf5af88000 1576K r-x-- /lib/x86_64-linux-gnu/libc-2.13.so 00007fcf5b112000 2044K ----- /lib/x86_64-linux-gnu/libc-2.13.so 00007fcf5b311000 16K r---- /lib/x86_64-linux-gnu/libc-2.13.so 00007fcf5b315000 4K rw--- /lib/x86_64-linux-gnu/libc-2.13.so 00007fcf5b316000 24K rw--- [ anon ] 00007fcf5b31c000 132K r-x-- /lib/x86_64-linux-gnu/ld-2.13.so 00007fcf5b512000 12K rw--- [ anon ] 00007fcf5b539000 12K rw--- [ anon ] 00007fcf5b53c000 4K r---- /lib/x86_64-linux-gnu/ld-2.13.so 00007fcf5b53d000 8K rw--- /lib/x86_64-linux-gnu/ld-2.13.so 00007fff7efd8000 132K rw--- [ stack ] 00007fff7efff000 4K r-x-- [ anon ] ffffffffff600000 4K r-x-- [ anon ] total 3984K
This output is how memory “looks” to the mem_munch process. If mem_munch asks the operating system for 00007fcf5af88000
, it will get libc. If it asks for 00007fcf5b31c000
, it will get the ld library.
This output is a bit dense and abstract, so let’s look at how some more familiar memory usage shows up. Change our program to put some memory on the stack and some on the heap, then pause.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
int main() {
int on_stack, *on_heap;
// local variables are stored on the stack
on_stack = 42;
printf("stack address: %p\n", &on_stack);
// malloc allocates heap memory
on_heap = (int*)malloc(sizeof(int));
printf("heap address: %p\n", on_heap);
printf("run `pmap %d`\n", getpid());
pause();
}
$ ./mem_munch stack address: 0x7fff497670bc heap address: 0x1b84010 run `pmap 11972`
Again, your exact numbers will probably be different than mine.
Before you kill mem_munch, run pmap on it:
$ pmap 11972 11972: ./mem_munch 0000000000400000 4K r-x-- /home/user/mem_munch 0000000000600000 4K r---- /home/user/mem_munch 0000000000601000 4K rw--- /home/user/mem_munch 0000000001b84000 132K rw--- [ anon ]00007f3ec4d98000 1576K r-x-- /lib/x86_64-linux-gnu/libc-2.13.so 00007f3ec4f22000 2044K ----- /lib/x86_64-linux-gnu/libc-2.13.so 00007f3ec5121000 16K r---- /lib/x86_64-linux-gnu/libc-2.13.so 00007f3ec5125000 4K rw--- /lib/x86_64-linux-gnu/libc-2.13.so 00007f3ec5126000 24K rw--- [ anon ] 00007f3ec512c000 132K r-x-- /lib/x86_64-linux-gnu/ld-2.13.so 00007f3ec5322000 12K rw--- [ anon ] 00007f3ec5349000 12K rw--- [ anon ] 00007f3ec534c000 4K r---- /lib/x86_64-linux-gnu/ld-2.13.so 00007f3ec534d000 8K rw--- /lib/x86_64-linux-gnu/ld-2.13.so 00007fff49747000 132K rw--- [ stack ] 00007fff497bb000 4K r-x-- [ anon ] ffffffffff600000 4K r-x-- [ anon ] total 4116K
Note that there’s a new entry between the final mem_munch section and libc-2.13.so. What could that be?
# from pmap
0000000001b84000 132K rw--- [ anon ]
# from our program
heap address: 0x1b84010
The addresses are almost the same. That block ([ anon ]
) is the heap. (pmap labels blocks of memory that aren’t backed by a file [ anon ]
. We’ll get into what being “backed by a file” means in a sec.)
The second thing to notice:
# from pmap
00007fff49747000 132K rw--- [ stack ]
# from our program
stack address: 0x7fff497670bc
And there’s your stack!
One other important thing to notice: this is how memory “looks” to your program, not how memory is actually laid out on your physical hardware. Look at how much memory mem_munch has to work with. According to pmap, mem_munch can address memory between address 0x0000000000400000
and 0xffffffffff600000
(well, actually 0x00007fffffffffffffff
, beyond that is special). For those of you playing along at home, that’s almost 10 million terabytes of memory. That’s a lot of memory. (If your computer has that kind of memory, please leave your address and times you won’t be at home.)
So, the amount of memory the program can address is kind of ridiculous. Why does the computer do this? Well, lots of reasons, but one important one is that this means you can address more memory than you actually have on the machine and let the operating system take care of making sure the right stuff is in memory when you try to access it.
Memory Mapped Files
Memory mapping a file basically tells the operating system to load the file so the program can access it as an array of bytes. Then you can treat a file like an in-memory array.
For example, let’s make a (pretty stupid) random number generator ever by creating a file full of random numbers, then mmap-ing it and reading off random numbers.
First, we’ll create a big file called random (note that this creates a 1GB file, so make sure you have the disk space and be patient, it’ll take a little while to write):
$ dd if=/dev/urandom bs=1024 count=1000000 of=/home/user/random 1000000+0 records in 1000000+0 records out 1024000000 bytes (1.0 GB) copied, 123.293 s, 8.3 MB/s $ ls -lh random -rw-r--r-- 1 user user 977M 2011-08-29 16:46 random
Now we’ll mmap random and use it to generate random numbers.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/mman.h>
int main() {
char *random_bytes;
FILE *f;
int offset = 0;
// open "random" for reading
f = fopen("/home/user/random", "r");
if (!f) {
perror("couldn't open file");
return -1;
}
// we want to inspect memory before mapping the file
printf("run `pmap %d`, then press <enter>", getpid());
getchar();
random_bytes = mmap(0, 1000000000, PROT_READ, MAP_SHARED, fileno(f), 0);
if (random_bytes == MAP_FAILED) {
perror("error mapping the file");
return -1;
}
while (1) {
printf("random number: %d (press <enter> for next number)", *(int*)(random_bytes+offset));
getchar();
offset += 4;
}
}
$ ./mem_munch run `pmap 12727`, then press <enter>
The program hasn’t done anything yet, so the output of running pmap will basically be the same as it was above (I’ll omit it for brevity). However, if we continue running mem_munch by pressing enter, our program will mmap random.
Now if we run pmap it will look something like:
$ pmap 12727 12727: ./mem_munch 0000000000400000 4K r-x-- /home/user/mem_munch 0000000000600000 4K r---- /home/user/mem_munch 0000000000601000 4K rw--- /home/user/mem_munch 000000000147d000 132K rw--- [ anon ] 00007fe261c6f000 976564K r--s- /home/user/random00007fe29d61c000 1576K r-x-- /lib/x86_64-linux-gnu/libc-2.13.so 00007fe29d7a6000 2044K ----- /lib/x86_64-linux-gnu/libc-2.13.so 00007fe29d9a5000 16K r---- /lib/x86_64-linux-gnu/libc-2.13.so 00007fe29d9a9000 4K rw--- /lib/x86_64-linux-gnu/libc-2.13.so 00007fe29d9aa000 24K rw--- [ anon ] 00007fe29d9b0000 132K r-x-- /lib/x86_64-linux-gnu/ld-2.13.so 00007fe29dba6000 12K rw--- [ anon ] 00007fe29dbcc000 16K rw--- [ anon ] 00007fe29dbd0000 4K r---- /lib/x86_64-linux-gnu/ld-2.13.so 00007fe29dbd1000 8K rw--- /lib/x86_64-linux-gnu/ld-2.13.so 00007ffff29b2000 132K rw--- [ stack ] 00007ffff29de000 4K r-x-- [ anon ] ffffffffff600000 4K r-x-- [ anon ] total 980684K
This is very similar to before, but with an extra line (bolded), which kicks up virtual memory usage a bit (from 4MB to 980MB).
However, let’s re-run pmap with the -x option. This shows the resident set size (RSS): only 4KB of random are resident. Resident memory is memory that’s actually in RAM. There’s very little of random in RAM because we’ve only accessed the very start of the file, so the OS has only pulled the first bit of the file from disk into memory.
pmap -x 12727 12727: ./mem_munch Address Kbytes RSS Dirty Mode Mapping 0000000000400000 0 4 0 r-x-- mem_munch 0000000000600000 0 4 4 r---- mem_munch 0000000000601000 0 4 4 rw--- mem_munch 000000000147d000 0 4 4 rw--- [ anon ] 00007fe261c6f000 0 4 0 r--s- random 00007fe29d61c000 0 288 0 r-x-- libc-2.13.so 00007fe29d7a6000 0 0 0 ----- libc-2.13.so 00007fe29d9a5000 0 16 16 r---- libc-2.13.so 00007fe29d9a9000 0 4 4 rw--- libc-2.13.so 00007fe29d9aa000 0 16 16 rw--- [ anon ] 00007fe29d9b0000 0 108 0 r-x-- ld-2.13.so 00007fe29dba6000 0 12 12 rw--- [ anon ] 00007fe29dbcc000 0 16 16 rw--- [ anon ] 00007fe29dbd0000 0 4 4 r---- ld-2.13.so 00007fe29dbd1000 0 8 8 rw--- ld-2.13.so 00007ffff29b2000 0 12 12 rw--- [ stack ] 00007ffff29de000 0 4 0 r-x-- [ anon ] ffffffffff600000 0 0 0 r-x-- [ anon ] ---------------- ------ ------ ------ total kB 980684 508 100
If the virtual memory size (the Kbytes column) is all 0s for you, don’t worry about it. That’s a bug in Debian/Ubuntu’s -x option. The total is correct, it just doesn’t display correctly in the breakdown.
You can see that the resident set size, the amount that’s actually in memory, is tiny compared to the virtual memory. Your program can access any memory within a billion bytes of 0x00007fe261c6f000, but if it accesses anything past 4KB, it’ll probably have to go to disk for it*.
What if we modify our program so it reads the whole file/array of bytes?
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/mman.h>
int main() {
char *random_bytes;
FILE *f;
int offset = 0;
// open "random" for reading
f = fopen("/home/user/random", "r");
if (!f) {
perror("couldn't open file");
return -1;
}
random_bytes = mmap(0, 1000000000, PROT_READ, MAP_SHARED, fileno(f), 0);
if (random_bytes == MAP_FAILED) {
printf("error mapping the file\n");
return -1;
}
for (offset = 0; offset < 1000000000; offset += 4) {
int i = *(int*)(random_bytes+offset);
// to show we're making progress
if (offset % 1000000 == 0) {
printf(".");
}
}
// at the end, wait for signal so we can check mem
printf("\ndone, run `pmap -x %d`\n", getpid());
pause();
}
$ pmap -x 5378 5378: ./mem_munch Address Kbytes RSS Dirty Mode Mapping 0000000000400000 0 4 4 r-x-- mem_munch 0000000000600000 0 4 4 r---- mem_munch 0000000000601000 0 4 4 rw--- mem_munch 0000000002271000 0 4 4 rw--- [ anon ] 00007fc2aa333000 0 976564 0 r--s- random 00007fc2e5ce0000 0 292 0 r-x-- libc-2.13.so 00007fc2e5e6a000 0 0 0 ----- libc-2.13.so 00007fc2e6069000 0 16 16 r---- libc-2.13.so 00007fc2e606d000 0 4 4 rw--- libc-2.13.so 00007fc2e606e000 0 16 16 rw--- [ anon ] 00007fc2e6074000 0 108 0 r-x-- ld-2.13.so 00007fc2e626a000 0 12 12 rw--- [ anon ] 00007fc2e6290000 0 16 16 rw--- [ anon ] 00007fc2e6294000 0 4 4 r---- ld-2.13.so 00007fc2e6295000 0 8 8 rw--- ld-2.13.so 00007fff037e6000 0 12 12 rw--- [ stack ] 00007fff039c9000 0 4 0 r-x-- [ anon ] ffffffffff600000 0 0 0 r-x-- [ anon ] ---------------- ------ ------ ------ total kB 980684 977072 104
Now if we access any part of the file, it will be in RAM already. (Probably. Until something else kicks it out.) So, our program can access a gigabyte of memory, but the operating system can lazily load it into RAM as needed.
And that’s why your virtual memory is so damn high when you’re running MongoDB.
Left as an exercise to the reader: try running pmap on a mongod process before it’s done anything, once you’ve done a couple operations, and once it’s been running for a long time.
This isn’t strictly true**. The kernel actually says, “If they want the first N bytes, they’re probably going to want some more of the file” so it’ll load, say, the first dozen KB of the file into memory but only tell the process about 4KB. When your program tries to access this memory that is in RAM, but it didn’t know was in RAM, it’s called a minor page fault (as opposed to a major page fault when it actually has to hit disk to load new info). back to context
This note is also not strictly true. In fact, the whole file will probably be in memory before you map anything because you just wrote the thing with dd. So you’ll just be doing minor page faults as your program “discovers” it.
相关文章:

留不住客户?该从你的系统上找找原因了
本篇文章暨 CSDN《中国 101 计划》系列数字化转型场景之一。 《中国 101 计划——探索企业数字化发展新生态》为 CSDN 联合《新程序员》、GitCode.net 开源代码仓共同策划推出的系列活动,寻访一百零一个数字化转型场景,聚合呈现并开通评选通道࿰…

系统配置文件备份比较
客户的系统出各种问题,这次出了问题整整一天都没找出原因,都红脸了,最后发现是系统配置文件被改掉了,简直不能忍,所以写了这个脚本,放到定时任务里面,每天备份比较配置文件import difflib impor…

RPC是什么?为什么要学习RPC?
随着近几年分布式、微服务架构的火热,RPC在开发工作中使用的越来越多,也变的越来越重要。 今天我们来看RPC是什么,为什么要了解RPC,通过学习RPC我们能掌握什么内容? 什么是「RPC」 RPC 全称 Remote Procedure Call, wikipedia的部…

Lua学习笔记6:C++和Lua的相互调用
曾经一直用C写代码。话说近期刚换工作。项目组中的是cocos2dx-lua,各种被虐的非常慘啊有木有。新建cocos2dx-lua项目。打开class能够发现,事实上就是C项目啦,只是为什么仅仅有一类Appdelegate类呢?哈哈,我相信聪明的你一定猜到了&…

Redis消息通知系统的实现
Redis消息通知系统的实现Posted on 2012-02-29by 老王 http://huoding.com/2012/02/29/146最近忙着用Redis实现一个消息通知系统,今天大概总结了一下技术细节,其中演示代码如果没有特殊说明,使用的都是PhpRedis扩展来实现的。内存比如要推送一…

用 Python 实现答题卡识别!
作者 | 棒子胡豆来源丨CSDN博客答题卡素材图片:思路读入图片,做一些预处理工作。进行轮廓检测,然后找到该图片最大的轮廓,就是答题卡部分。进行透视变换,以去除除答题卡外的多余部分,并且可以对答题卡进行校…
Confluence 6 计划任务
管理员控制台能够允许你对 Confluence 运行的计划任务进行计划的调整,这些计划任务将会按照你的调整按时执行。可以按照计划执行的任务如下: Confluence 站点备份存储优化任务,清理 Confluence 的临时目录中的文件和缓存索引优化任务…

PHP共享内存段
在asp.net和java中都有共享内存,php除了可以使用Memcached等方式变通以外其实php也是支持共享内存的!需要安装扩展shmop 找到php安装源文件目录# cd /usr/local/php-5.4.0/ext/shmop # /usr/local/php/bin/phpize # ./configure --with-php-config/usr/l…

马尔科夫随机场的基本概念
1、随机过程: 描写叙述某个空间上粒子的随机运动过程的一种方法。它是一连串随机事件动态关系的定量描写叙述。随机过程与其他数学分支,如微分方程、复变函数等有密切联系。是自然科学、project科学及社会科学等领域研究随机现象的重要工具。 2、马尔科夫…

从事了两年 AI 研究,我学到了什么?
作者 | Tom Silver译者 | 弯月出品 | CSDN我从事人工智能研究的工作已经有两年了,有朋友问我都学到了什么,所以我想借本文分享一些迄今为止积累的经验教训。我将在本文中分享一些常见的经历,还会讨论相对具体的人工智能行业技巧。希望对大家能…

Windows server 2008普通用户不能远程登录问题
1、查登录权限 如果文件服务器没有为用户授权,那么用户自然就不能远程登录服务器系统了,为此笔者决定先仔细检查一下文件服务器系统是否为自己使用的登录账号,授予了远程登录权限。在进行这种检查时,笔者先是在文件服务器本地以系…

面向小白的最全 Python 可视化教程,超全的!
作者 | 俊欣来源丨关于数据分析与可视化今天小编总结归纳了若干个常用的可视化图表,并且通过调用plotly、matplotlib、altair、bokeh和seaborn等模块来分别绘制这些常用的可视化图表,最后无论是绘制可视化的代码,还是会指出来的结果都会通过调…

Atitit.文件搜索工具 attilax 总结
Atitit.文件搜索工具 attilax 总结 1. 指定目录按照体积大小精确搜索1 1.1. File Seeker 4.5 版本的可以,3.5版本的不行。。1 2. 按照文件内容搜索1 2.1. File Seeker2 2.2. Notepad2 2.3. FileLocator Pro 是一款专业的文件搜索软件,2 2.4. 百度硬盘搜索…

ulimit -SHn 65535 含义
linux下用ulimit设置连接数最大值,默认是1024.在高负载下要设置为更高,但最高只能为65535. ulimit只能做临时修改,重启后失效。可以加入ulimit -SHn 65535到 /etc/rc.local 每次启动启用。终极解除 Linux 系统的最大进程数和最大文件打开数限…

5.7-基于Binlog+Position的复制搭建
基本环境 MasterSlaveMySQL版本MySQL-5.7.16-X86_64MySQL-5.7.16-X86_64IP192.168.56.156192.168.56.157Port33063306数据库环境的部署:两边安装好相同的数据库软件,初始化,可以启动起来。检查事项:两边防火墙是否开启,…

PHP消息队列httpsqs安装与使用无错版
项目网址:http://code.google.com/p/httpsqs/使用文档:http://blog.s135.com/httpsqs/ 说明:由于需要安装的东西有些多,原文可能写的有些简略,所以适当补充了1.安装libevent-2.0.12-stable.tar.gzwget http://httpsqs.…

Windows Server 2012 系统群集
Windows Server 2012 系统群集本次将测试Windows Server 2012 系统群集功能。实验环境:4台服务器都为Windows Server 2012 DataCenter操作系统SRV2012服务器安装iSCSI目标服务器角色并配置2块虚拟磁盘给两台群集服务器共享使用。群集服务器安装群集功能,…

Python 中最强大的错误重试库
作者 | 费弗里来源丨Python大数据分析1 简介我们在编写程序尤其是与网络请求相关的程序,如调用web接口、运行网络爬虫等任务时,经常会遇到一些偶然发生的请求失败的状况,这种时候如果我们仅仅简单的捕捉错误然后跳过对应任务,肯定…

Spring Cloud云架构 - SSO单点登录之OAuth2.0登录流程(2)
上一篇是站在巨人的肩膀上去研究OAuth2.0,也是为了快速帮助大家认识OAuth2.0,闲话少说,我根据框架中OAuth2.0的使用总结,画了一个简单的流程图(根据用户名密码实现OAuth2.0的登录认证): 上面的图…

php的POSIX 函数以及进程测试
参考:http://cn.php.net/manual/zh/ref.posix.php <?phpecho posix_getpid(); //8805sleep(10);?>再用 #ps -ax这个时候如果多开开个浏览器请求,就会发现Apache自动增加了几个新的进程我们发现并非一直请求同一个进程重启apache # /usr/local/ap…

CAS (10) —— JBoss EAP 6.4下部署CAS时出现错误exception.message=Error decoding flow execution的解决办法...
CAS (10) —— JBoss EAP 6.4下部署CAS时出现错误exception.messageError decoding flow execution的解决办法 jboss版本: jboss-eap-6.4-CVE-2015-7501 jdk版本: 1.7.0_79 cas版本: cas 4.1.3 参考来源: Nabble: exception.messageErrordecodingflowexecution Nabble: Caused …

昇思MindSpore1.6发布 AI开发者体验再升级
智能时代,AI技术正在发挥至关重要的作用,而开源的深度学习框架不仅能够降低AI开发者的门槛,而且能够极大节省成本与时间,成为创新的重要推手。2022年3月26-27日,昇思MindSpore TechDay活动线上成功举办,包含…

深入解析:TRUNCATE TABLE 的内部原理解析与恢复思路
摘要 众所周知,truncate table 是一种快速清空表内数据的一种方式,与 delete 方式不同,truncate 只产生非常少的 redo 和 undo,就实现了清空表数据并降低表 HWM 的功能。本文主要围绕 truncate table 的实现原理和 truncate table…

Linux exec与重定向
exec和source都属于bash内部命令(builtins commands),在bash下输入man exec或man source可以查看所有的内部命令信息。 bash shell的命令分为两类:外部命令和内部命令。外部命令是通过系统调用或独立的程序实现的,如se…

俄罗斯 Android 系统受限,或将转用 HarmonyOS!
整理 | 郑丽媛出品 | CSDN近一个月来,受当前局势影响,部分底层工具、基础软件、开源项目已相继宣布在俄罗斯停服,期间不少人因此担忧:同出自美国且占据极大智能手机市场的 Android 和 iOS 是否会趁机“作乱”?结果&…

Ios应用网络安全之https
戴维营教育原创文章,转载请注明出处。我们的梦想是做最好的iOS开发培训!iOS应用网络安全之HTTPS1. HTTPS/SSL的基本原理安全套接字层 (Secure Socket Layer, SSL) 是用来实现互联网安全通信的最普遍的标准。Web 应用程序使用 HTTPS(基于 SSL …

云原生应用的10大关键属性
2019独角兽企业重金招聘Python工程师标准>>> “云原生”是用于描述基于容器的环境的术语,而Kubernetes是一个运行云原生应用程序工作负载的理想平台。 开发人员在设计云原生应用程序时,一定要牢记本文内这10个关键属性! “云原生&…

grep 正则表达式及选项以及注意
说明:在原文基础上稍作了修改grep命令简介: 在ex编辑器(我没用过)中,启动ex编辑器后要查找某个字符串时,在ex的命令提示符后键入::/pattern/p:/g/pattern/pgrep这个名字就由来如此。其中p的含义是print&…

iOS_25彩票_幸运转盘
终于效果图: 各个view的关系图: 背景圆盘(须要扣图处理)LuckyBaseBackground.png 盖在背景圆盘上面的转盘 LuckyRotateWheel.png 代表一个星座或生肖的button背景图片 要创建12个,并以最下方中点为锚点进行旋转 对背景圆盘进行扣图,并在其上面盖上转盘图片的核心代码 在自己定义…

Python 自动化办公之 Excel 对比工具
作者 | 周萝卜来源丨萝卜大杂烩今天我们继续分享真实的自动化办公案例,希望各位 Python 爱好者能够从中得到些许启发,在自己的工作生活中更多的应用 Python,使得工作事半功倍!需求由于工作当中经常需要对比前后两个 Excel 文件&am…