Linux内核源代码情景分析-exit()

    执行完/bin/echo之后,会调动do_exit,销毁子进程:

    我们还是先从系统调用exit()说起,先来看exit()的实现,进入到内核态执行sys_exit。

asmlinkage long sys_exit(int error_code)
{
	do_exit((error_code&0xff)<<	8);
}
NORET_TYPE void do_exit(long code)
{
	struct task_struct *tsk = current;

	if (in_interrupt())//中断服务不能中断
		panic("Aiee, killing interrupt handler!");
	if (!tsk->pid)//空转idle进程是不允许退出的
		panic("Attempted to kill the idle task!");
	if (tsk->pid == 1)//init进程是不允许退出的
		panic("Attempted to kill init!");
	tsk->flags |= PF_EXITING;
	del_timer_sync(&tsk->real_timer);

fake_volatile:
#ifdef CONFIG_BSD_PROCESS_ACCT
	acct_process(code);
#endif
	__exit_mm(tsk);//如果通过指针共享,只是减少共享计数mm->mm_users。如果自立门户,则释放mm_struct,vm_struct;释放页目录表,页表

	lock_kernel();
	sem_exit();//信号相关,看完进程间通信再说
	__exit_files(tsk);//如果通过指针共享,只是减少共享计数files->count。如果自立门户,那就要释放files_struct数据结构
	__exit_fs(tsk);//如果通过指针共享,只是减少共享计数fs->count。如果自立门户,那就要释放fs_struct数据结构
	exit_sighand(tsk);//如果通过指针共享,只是减少共享计数sig->count。如果自立门户,那就要释放signal_struct数据结构
	exit_thread();//空函数

	if (current->leader)
		disassociate_ctty(1);

	put_exec_domain(tsk->exec_domain);
	if (tsk->binfmt && tsk->binfmt->module)
		__MOD_DEC_USE_COUNT(tsk->binfmt->module);

	tsk->exit_code = code;
	exit_notify();//将当前进程设置为僵死状态;并给父进程发信号;其当前进程的子进程的父进程设置为init进程
	schedule();
	BUG();
/*
 * In order to get rid of the "volatile function does return" message
 * I did this little loop that confuses gcc to think do_exit really
 * is volatile. In fact it's schedule() that is volatile in some
 * circumstances: when current->state = ZOMBIE, schedule() never
 * returns.
 *
 * In fact the natural way to do all this is to have the label and the
 * goto right after each other, but I put the fake_volatile label at
 * the start of the function just in case something /really/ bad
 * happens, and the schedule returns. This way we can try again. I'm
 * not paranoid: it's just that everybody is out to get me.
 */
	goto fake_volatile;
}


    __exit_mm,子进程自立门户,释放mm_struct,vm_struct;释放页目录表,页表:

static inline void __exit_mm(struct task_struct * tsk)
{
	struct mm_struct * mm = tsk->mm;

	mm_release();
	if (mm) {
		atomic_inc(&mm->mm_count);
		if (mm != tsk->active_mm) BUG();
		/* more a memory barrier than a real lock */
		task_l
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抱歉,我是一个自然语言处理的AI,无法直接生成代码,但我可以提供一个大致的思路供您参考: 首先,需要包含一些头文件,如: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <elf.h> ``` 然后,需要定义一些数据结构,如: ```c typedef struct { char* name; // 库名 void* addr; // 库地址 int depcnt; // 依赖库数量 struct Library** dep; // 依赖库列表 Elf64_Dyn** dynInfo; // 动态信息 } Library; Library** libraries = NULL; int libcnt = 0; ``` 接着,需要实现一些函数,如: ```c void RelocLibrary(Library* lib, int mode) { if (strcmp(lib->name, "lib.so.6") == 0) { return; } for (int j = 0; j < lib->depcnt; ++j) { RelocLibrary(lib->dep[j], mode); } Elf64_Sym* sym = NULL; Elf64_Rela* frel = NULL; int relsz = 0; char* str = NULL; if (lib->dynInfo[DT_SYMTAB]) { sym = (typeof(sym))lib->dynInfo[DT_SYMTAB]->d_un.d_ptr; } if (lib->dynInfo[DT_JMPREL]) { frel = (typeof(frel))lib->dynInfo[DT_JMPREL]->d_un.d_ptr; } if (lib->dynInfo[DT_PLTRELSZ]) { relsz = lib->dynInfo[DT_PLTRELSZ]->d_un.d_val / sizeof(Elf64_Rela); } if (lib->dynInfo[DT_STRTAB]) { str = (char*)lib->dynInfo[DT_STRTAB]->d_un.d_ptr; } for (int i = 0; i < relsz; ++i, ++frel) { Elf64_Addr* got = (void*)(lib->addr + frel->r_offset); if (mode == RTLD_LAZY) { *got += lib->addr; continue; } void* result = NULL; for (int j = 0; j < lib->depcnt; ++j) { void* tmp = symbolLookup(lib->dep[j], &str[sym[ELF64_R_SYM(frel->r_info)].st_name]); if (tmp != NULL) { result = tmp + frel->r_addend; break; } } *(uint64_t*)(lib->addr + frel->r_offset) = (uint64_t)result; } } void* symbolLookup(Library* lib, const char* name) { Elf64_Sym* sym = NULL; char* str = NULL; if (lib->dynInfo[DT_SYMTAB]) { sym = (typeof(sym))lib->dynInfo[DT_SYMTAB]->d_un.d_ptr; } if (lib->dynInfo[DT_STRTAB]) { str = (char*)lib->dynInfo[DT_STRTAB]->d_un.d_ptr; } for (int i = 0; i < lib->dynInfo[DT_PLTRELSZ]->d_un.d_val / sizeof(Elf64_Rela); ++i) { if (ELF64_ST_TYPE(sym[i].st_info) != STT_FUNC) { continue; } if (strcmp(&str[sym[i].st_name], name) == 0) { return (void*)(lib->addr + sym[i].st_value); } } return NULL; } Library* loadLibrary(const char* name, int mode) { char buf[256]; Library* lib = (Library*)malloc(sizeof(Library)); lib->name = strdup(name); snprintf(buf, sizeof(buf), "/usr/lib/%s", name); FILE* fp = fopen(buf, "rb"); if (fp == NULL) { free(lib); return NULL; } fseek(fp, 0, SEEK_END); size_t size = ftell(fp); fseek(fp, 0, SEEK_SET); void* addr = malloc(size); fread(addr, 1, size, fp); fclose(fp); Elf64_Ehdr* ehdr = (Elf64_Ehdr*)addr; Elf64_Phdr* phdr = (Elf64_Phdr*)((char*)ehdr + ehdr->e_phoff); for (int i = 0; i < ehdr->e_phnum; ++i) { if (phdr[i].p_type == PT_LOAD) { memcpy((void*)phdr[i].p_vaddr, (void*)((char*)addr + phdr[i].p_offset), phdr[i].p_filesz); memset((void*)(phdr[i].p_vaddr + phdr[i].p_filesz), 0, phdr[i].p_memsz - phdr[i].p_filesz); } } Elf64_Dyn* dyn = (Elf64_Dyn*)((char*)ehdr + ehdr->e_dynamic); lib->dynInfo = (Elf64_Dyn**)malloc(sizeof(Elf64_Dyn*) * DT_NUM); memset(lib->dynInfo, 0, sizeof(Elf64_Dyn*) * DT_NUM); while (dyn->d_tag != DT_NULL) { if (dyn->d_tag < DT_NUM) { lib->dynInfo[dyn->d_tag] = dyn; } dyn++; } lib->addr = addr; lib->depcnt = 0; lib->dep = NULL; if (lib->dynInfo[DT_NEEDED]) { char* str = (char*)lib->dynInfo[DT_STRTAB]->d_un.d_ptr; char* ptr = (char*)lib->dynInfo[DT_NEEDED]->d_un.d_ptr; while (*ptr) { char* depname = ptr; ptr += strlen(depname) + 1; if (mode == RTLD_LAZY) { if (strcmp(depname, "libpthread.so.0") == 0 || strcmp(depname, "libc.so.6") == 0) { continue; } } if (strcmp(depname, lib->name) == 0) { continue; } Library* dep = loadLibrary(depname, mode); if (dep == NULL) { fprintf(stderr, "cannot load library '%s'\n", depname); exit(1); } lib->dep = (Library**)realloc(lib->dep, sizeof(Library*) * (lib->depcnt + 1)); lib->dep[lib->depcnt] = dep; lib->depcnt++; } } libraries = (Library**)realloc(libraries, sizeof(Library*) * (libcnt + 1)); libraries[libcnt] = lib; libcnt++; return lib; } void unloadLibrary(Library* lib) { for (int i = 0; i < lib->depcnt; ++i) { unloadLibrary(lib->dep[i]); } free(lib->dep); free(lib->dynInfo); free(lib->name); free(lib->addr); free(lib); } ``` 最后,可以在主函数中调用这些函数,如: ```c int main() { Library* lib = loadLibrary("libtest.so", RTLD_NOW); RelocLibrary(lib, RTLD_NOW); void (*func)() = symbolLookup(lib, "test"); if (func != NULL) { func(); } unloadLibrary(lib); return 0; } ``` 当然,这只是一个大致的实现思路,具体实现还需要根据需求进行适当的修改和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值