c 代码调用汇编代码

汇编 world.asm

SECTION .TEXT
    GLOBAL calc

calc:
    mov rax,rdi
    add rax,r9
    ret

编译:

 $ nasm -f elf64 world.asm -o world.o

C 代码:

#include <stdio.h>

int main(int argc, char *argv[]) {
    extern int calc(int, int, int, int, int, int);
    printf("%d\n", calc(1, 3, 5, 7, 9, 11));
    return 0;
}

合在一块编译成目标文件 并执行

 $ gcc hello.c world.o -o hello
 $ ./hello
  1. 从 C 代码产生汇编代码:

    gcc -S  -Og test.c
  2. 汇编特殊指令:

    .LC0 local constant, e.g string literal.
    .LFB0 local function beginning,
    .LFE0 local function ending,
  3. 源代码只预处理, 编译, 汇编, 链接

    gcc -E -o hello.i hello.c
    gcc -S -o hello.s hello.c
    gcc -c -o hello.o hello.c
    gcc -o hello hello.c

C 语言参考

函数: 表达式 (操作符 + 操作数(变量 + 常量))
数据: 变量 + 常量

预处理

  1. #include <stdio.h>
  2. #define STEP 20 //符号常量

数据类型

signed + unsigned

  1. char
  2. short (short int)
  3. int
  4. long (long int)
  5. float
  6. double (浮点默认)
  7. long double

函数

  1. if the return type is omitted, int is assumed -> dummy(){}
  2. C does not allow functions to be defined inside other functions.

Input/Output

char c = getchar();
putchar(c);

编译

  1. cc main.c getline.c strindex.c
  2. c main.c getline.o strindex.o

关于 Java 应用的 线程栈内存大小

对于 Java 应用, 对于内存的占用, 主要是Java堆, 通常我们为了性能考虑, 会对堆设置最大值, 否则 JVM 就会根据它锁了解的系统参数, 设置一个可能的最大值. 除了堆之外, 其实还有好几部分, 也可能占用不少内存. 比如元数据区(老年代), 线程栈, 编译后的代码, GC 程序, 编译器, JVM符号表之类的. 这里可以通过添加启动参数: -XX:NativeMemoryTracking=summary or -XX:NativeMemoryTracking=detail 来追踪原生内存的占用. 比如:
nmt.png

比如上面的截图中, kiyomi 看到 Thread 部分 reserve 了 1052M, 已经提交占用了 1052M, 查看 thread dump, 发现现在大概有 1003 个线程, 基本每个线程占用 1M.

另外我们知道, 可以使用 Xss 参数设置每个线程栈的大小, 比如:
-Xss1m
-Xss1024k
-Xss1048576
上面的参数等同于:
-XX:ThreadStackSize

在 Linux 64 bit 上, 默认是 1MB. 从 Oracle 的官方文档: https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
可以看到具体的说明.

从上面的文档可以看出, 每个栈在 64bit 的 Linux 上使用 1M, 可是我从另外一个机器上看到大概有 20K 个线程, 可是占用的内存并不是 20G. 于是我们看到 对于 IBM JDK 和 OpenJ9 JDK 它们都用 3 个参数:

  1. -Xiss<size> Set initial Java thread stack size 2 KB
  2. -Xss<size> Set maximum Java thread stack size 320 KB (31/32-bit); 1024 KB (64-bit)
  3. -Xssi<size> Set Java thread stack size increment 16 KB
    这里它们对 Xss 的解读是最大的可用栈大小. 所以, 就有个疑问, 对于 HotSpot JDK, 是每个栈必须占用 1M, 还是这也是最大值???

更新:
根据这个 Bug 描述: https://bugs.openjdk.java.net/browse/JDK-8191369
应该是最大值, 之前的 NMT 简单的把 reserved 和 commited 置成 线程数 * Xss. 其实真正的 committed 可能并么有这么多, 虽然声明使用 1M 虚拟内存, 可能实际使用的物理内存页比较少. 所以 commited 比较少.

比如下面这个例子, 该 JVM 在一个 container 里面, 设置的最大可用内存是 16G, 已经使用 13.58G. 当前线程数是 11266 个, 堆大小设置的是 8G, 可以看到 Thread 通过 NMT 显示的是大概 10G, 总的 commit 已经大约 20G. 其实这个 Thread 占用的都是根据线程数 * Xss 算出来的, 都是根据最大值算出来的, 所以其实最后算出的 commit 是不准的. 根据 top 可得到该进程的 RSS 大概是 10G. 所以可以推算 Thread 占用少于 2 个 G.

nmt1.png

修复之后的版本:
newNMT.png