Skip to main content

3 posts tagged with "linux"

View All Tags

环境变量是什么

· 3 min read

当我们使用shell 的命令env命令的时候可以看到很多字符串,那些就是这个进程的环境变量

环境变量怎么存

The first two arguments are just the same. The third argument envp gives the program’s environment; it is the same as the value of environ. See Environment Variables. POSIX.1 does not allow this three-argument form, so to be portable it is best to write main to take two arguments, and use the value of environ.

posix 相关文档

where argc is the argument count and argv is an array of character pointers to the arguments themselves. In addition, the following variable:

extern char **environ;

is initialized as a pointer to an array of character pointers to the environment strings. The argv and environ arrays are each terminated by a null pointer. The null pointer terminating the argv array is not counted in argc.

例子

下面是例子

#include <stdio.h>

extern char **environ;

int main(int argc, const char *argv[]) {
printf("environment variables:\n");
int i = 0;
while (environ[i]) {
printf("%p\t%s\n", environ[i], environ[i]);
i++;
}

printf("argv:\n");
for (int i = 0; i < argc; i++) {
printf("%p\t%s\n", argv[i], argv[i]);
}
}

编译后会把这些打印出来

gcc main.c -o main
dinosaur@dinosaur-X550VXK:~/test$ ./main
environment variables:
0x7ffc250920c7 XDG_VTNR=7
0x7ffc250920d2 LC_PAPER=zh_CN.UTF-8
0x7ffc250920e7 LC_ADDRESS=zh_CN.UTF-8
0x7ffc250920fe XDG_SESSION_ID=c1
0x7ffc25092110 XDG_GREETER_DATA_DIR=/var/lib/lightdm-data/dinosaur
0x7ffc25092144 LC_MONETARY=zh_CN.UTF-8
0x7ffc2509215c CLUTTER_IM_MODULE=xim
...

glibc变量

定义

定义在glibc-master/posix/environ.c

/* This file just defines the `__environ' variable (and alias `environ').  */

#include <unistd.h>
#include <stddef.h>

/* This must be initialized; we cannot have a weak alias into bss. */
char **__environ = NULL;
weak_alias (__environ, environ) // 弱引用 其实environ 就是__environ
...

读getenv

char *
getenv (const char *name)
{
size_t len = strlen (name);
char **ep;
uint16_t name_start;


...
name_start = *(const uint16_t *) name;
...
len -= 2;
name += 2;

for (ep = __environ; *ep != NULL; ++ep)
{
uint16_t ep_start = *(uint16_t *) *ep;

if (name_start == ep_start && !strncmp (*ep + 2, name, len)
&& (*ep)[len + 2] == '=')
return &(*ep)[len + 3];
}
...

return NULL;
}

写 putenv setenv

putenv setenv 都调用__add_to_environ

int
__add_to_environ (const char *name, const char *value, const char *combined,
int replace)
{
const size_t namelen = strlen (name);
size_t vallen;
...
vallen = strlen (value) + 1;
...
const size_t varlen = namelen + 1 + vallen;
...
memcpy (new_value, name, namelen);
new_value[namelen] = '=';
memcpy (&new_value[namelen + 1], value, vallen);
...
}

其实就是char ** environ 变量存着 key=value的字符串

如何以及什么时机继承

// todo 有空扒一下

总结

环境变量是一堆字符串,继承通过进程父子关系

1 环境变量的来源、原理与应用

2 glibc 文档

qemu调试内核

· 2 min read

相关参考

第一步

$ cd linux-4.16
$ make menuconfig
$ make -j8
  • 开启debug 信息
Kernel hacking  ---> 
[*] Kernel debugging
Compile-time checks and compiler options --->
[*] Compile the kernel with debug info
[*] Provide GDB scripts for kernel debugging
  • 关闭地址随机化 选中Processor type and features 然后关闭
 [*] 64-bit kernel                                                │ │  
│ │ General setup ---> │ │
│ │ [*] Enable loadable module support ---> │ │
│ │ -*- Enable the block layer ---> │ │
│ │ Processor type and features --->

反选 KASLR, 也就是关闭地址随机化

│ │    [ ]   Randomize the address of the kernel image (KASLR)   

为什么需要关闭地址随机

第二步

编译busybox,注意是静态链接,然后构建initramfs根文件系统

第三步

通过qemu 跑这个系统

qemu-system-x86_64  -kernel  /home/dinosaur/Downloads/linux-4.16/arch/x86/boot/bzImage  -hda qemu_rootfs.img  -append "root=/dev/sda rootfstype=ext4 rw"   -gdb tcp::1234

gdb 调试

gdb vmlinux
(gdb) target remote localhost:1234
b vfs_write

然后输出

(gdb) bt
#0 vfs_write (file=0xffff880006431700, buf=0x66506a <error: Cannot access memory at address 0x66506a>,
count=46, pos=0xffffc900000b7f08) at fs/read_write.c:529
#1 0xffffffff811a08cd in SYSC_write (count=<optimized out>, buf=<optimized out>, fd=<optimized out>)
at fs/read_write.c:589
#2 SyS_write (fd=<optimized out>, buf=6705258, count=46) at fs/read_write.c:581
#3 0xffffffff81001c8b in do_syscall_64 (regs=0xffff880006431700) at arch/x86/entry/common.c:287
#4 0xffffffff81a00071 in entry_SYSCALL_64 () at arch/x86/entry/entry_64.S:237
#5 0x0000000000000000 in ?? ()