好记性不如烂笔头。今天要做的学习是关于bionic目录下的代码。
首先需要看的是_errno.c这份代码。
volatile int* __errno( void ) { return &((volatile int*)__get_tls())[TLS_SLOT_ERRNO]; }
从上面可以看出,返回的是一个指向int类型的指针。
volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。
volatile的本意是“易变的”,不过翻译成“直接存取原始内存地址”更为合适。“易变”是因为外在因素引起的,象多线程,中断等,并不是因为用volatile修饰了的变量就是“易变”了,假如没有外因,即使用volatile定义,它也不会变化。
第二个需要说到的_set_errono.c的这份代码。
这个函数最终会被系统进行调用。
同时在这个函数里面,即使数据超过边界,依旧不会认为是个错误。因为在Linux中,错误的编码不会超过131.
if(n > -256) { return __set_errno(-n); } else { return n; }
OpenBSD是一个多平台的,基于4.4BSD的类UNIX操作系统,是BSD衍生出的三种免费操作系统(另外两种是NetBSD和FreeBSD)之一,被称为世界上最安全的操作系统
接下来需要学习的是arc4random.c。
static pthread_mutex_t _arc4_lock = PTHREAD_MUTEX_INITIALIZER; #define _ARC4_LOCK() pthread_mutex_lock(&_arc4_lock) #define _ARC4_UNLOCK() pthread_mutex_unlock(&_arc4_lock)
定义锁的作用是保护文件中的全局的变量。
只要注意这个文件是用来生成0~1之间的随机数就可以了。
接下来看一下basename.c这个类。
在这个文件中,仅仅存在一个函数,返回的是一个字符串。
if (bname == NULL) { bname = (char *)malloc(MAXPATHLEN); if (bname == NULL) return(NULL); }
很明显存在分配存储空间。
接下来看到的这个文件是bionic_clone这个文件。
主要查看里面的clone方法。
int clone(int (*fn)(void *), void *child_stack, int flags, void* arg, ...) { va_list args; int *parent_tidptr = NULL; void *new_tls = NULL; int *child_tidptr = NULL; int ret; /* extract optional parameters - they are cummulative */ va_start(args, arg); if (flags & (CLONE_PARENT_SETTID|CLONE_SETTLS|CLONE_CHILD_SETTID)) { parent_tidptr = va_arg(args, int*); } if (flags & (CLONE_SETTLS|CLONE_CHILD_SETTID)) { new_tls = va_arg(args, void*); } if (flags & CLONE_CHILD_SETTID) { child_tidptr = va_arg(args, int*); } va_end(args); ret = __bionic_clone(flags, child_stack, parent_tidptr, new_tls, child_tidptr, fn, arg); return ret; }
1、参数列表
2、父线程与子线程指针以及返回数值的定义。
接下来查看的文件是clearenv这个文件。
int clearenv(void) { char **P = environ; if (P != NULL) { for (; *P; ++P) *P = NULL; } return 0; }
由上面可以看出environ是一个纸箱指针的指针,也可以理解为是一个字符串的二维数组。
在dlmalloc文件中要注意下面的方法:
static size_t release_unused_segments(mstate m) { size_t released = 0; msegmentptr pred = &m->seg; msegmentptr sp = pred->next; while (sp != 0) { char* base = sp->base; size_t size = sp->size; msegmentptr next = sp->next; if (is_mmapped_segment(sp) && !is_extern_segment(sp)) { mchunkptr p = align_as_chunk(base); size_t psize = chunksize(p); /* Can unmap if first chunk holds entire segment and not pinned */ if (!cinuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) { tchunkptr tp = (tchunkptr)p; assert(segment_holds(sp, (char*)sp)); if (p == m->dv) { m->dv = 0; m->dvsize = 0; } else { unlink_large_chunk(m, tp); } if (CALL_MUNMAP(base, size) == 0) { released += size; m->footprint -= size; /* unlink obsoleted record */ sp = pred; sp->next = next; } else { /* back out if cannot unmap */ insert_large_chunk(m, tp, psize); } } } pred = sp; sp = next; } return released; }
在pthread-timers中主要关注下面的一个结构体的定义:
struct thr_timer { thr_timer_t* next; /* next in free list */ timer_t id; /* TIMER_ID_NONE iff free or dying */ clockid_t clock; pthread_t thread; pthread_attr_t attributes; thr_timer_func_t callback; sigval_t value; /* the following are used to communicate between * the timer thread and the timer_XXX() functions */ pthread_mutex_t mutex; /* lock */ pthread_cond_t cond; /* signal a state change to thread */ int volatile done; /* set by timer_delete */ int volatile stopped; /* set by _start_stop() */ struct timespec volatile expires; /* next expiration time, or 0 */ struct timespec volatile period; /* reload value, or 0 */ int volatile overruns; /* current number of overruns */ };
1、指向当前的空闲队列的指针
2、定义相关的线程 信号量 以及对应的回调的函数
3、定义一些在时间片的线程与一些函数之间互相调用的变量