本文将为大家介绍鸿蒙轻内核中的进程、线程、内存和网络四大基础功能,包括一些基础概念、实现功能和使用场景等,供想要深入了解鸿蒙操作系统的初学者学习参考。
从系统的角度看,进程是资源管理单元。进程可以使用或等待CPU、使用内存空间等系统资源,并独立于其它进程运行。
OpenHarmony内核的进程模块可以给用户提供多个进程,实现了进程之间的切换和通信,帮助用户管理业务程序流程。这样用户可以将更多的精力投入到业务功能的实现中。
OpenHarmony内核中的进程采用抢占式调度机制,支持时间片轮转调度方式和FIFO调度机制。
OpenHarmony内核的进程一共有32个优先级(0-31),用户进程可配置的优先级有22个(10-31),最高优先级为10,最低优先级为31。
高优先级的进程可抢占低优先级进程,低优先级进程必须在高优先级进程阻塞或结束后才能得到调度。
每一个用户态进程均拥有自己独立的进程空间,相互之间不可见,实现进程间隔离。
用户态根进程Init由内核态创建,其它用户态进程均由Init进程fork而来。
进程状态说明:
图 1 进程状态迁移示意图
进程状态迁移说明:
进程创建后,用户只能操作自己进程空间的资源,无法操作其它进程的资源(共享资源除外)。用户态允许进程挂起,恢复,延时等操作,同时也可以设置用户态进程调度优先级和调度策略,获取进程调度优先级和调度策略。进程结束的时候,进程会主动释放持有的进程资源,但持有的进程pid资源需要父进程通过wait/waitpid或父进程退出时回收。
OpenHarmony内核系统中的进程管理模块为用户提供下面几种功能:
表 1 进程管理模块功能
功能分类 | 接口名 | 描述 | 备注 |
---|---|---|---|
进程 | fork | 创建一个新进程。 | - |
exit | 终止进程。 | - | |
atexit | 注册正常进程终止的回调函数。 | - | |
abort | 中止进程执行。 | - | |
getpid | 获取进程ID。 | - | |
getppid | 获取父进程ID。 | - | |
getpgrp | 获取调用进程的进程组ID。 | - | |
getpgid | 获取进程的进程组ID。 | - | |
setpgrp | 设置调用进程的进程组ID。 | - | |
setpgid | 设置进程的进程组ID。 | - | |
kill | 给进程发送信号。 | 仅支持1-30号信号的发送。信号的默认行为不支持STOP及CONTINUE,无COREDUMP功能。不能屏蔽SIGSTOP、SIGKILL、SIGCONT。异步信号,发送信号给某进程后,直到该进程被调度后才会执行信号回调(为安全起见,杀死进程的动作是进程自己执行的,内核不能通过信号强制杀死对方)。进程消亡会发送SIGCHLD给父进程,发送动作无法取消。无法通过信号唤醒正在睡眠的进程。 | |
wait | 等待任意子进程结束并回收子进程资源。 | status的值可以由以下宏定义解析:WIFEXITED(status):如果子进程正常结束,它就返回真;否则返回假。WEXITSTATUS(status):如果WIFEXITED(status)为真,则可以用该宏取得子进程exit()返回的退出码。WTERMSIG(status) 仅支持以下情况:子进程触发异常结束后通过WTERMSIG获取的进程退出编号始终为SIGUSR2。不支持的操作:WIFSTOPPED、WSTOPSIG、WCOREDUMP 、WIFCONTINUED。 | |
waitpid | 等待子进程结束并回收子进程资源。 | options:不支持WUNTRACED,WCONTINUED;status的值可以由以下宏定义解析:WIFEXITED(status):如果子进程正常结束,它就返回真;否则返回假。WEXITSTATUS(status):如果WIFEXITED(status)为真,则可以用该宏取得子进程exit()返回的退出码。WTERMSIG(status)仅支持以下情况:子进程触发异常结束后通过WTERMSIG获取的进程退出编号始终为SIGUSR2。不支持:WIFSTOPPED 、WSTOPSIG、WCOREDUMP 、WIFCONTINUED。 | |
调度 | getpriority | 获取指定ID的静态优先级。 | 不支持:PRIO_PGRP、PRIO_USER。无动态优先级概念,用于设置静态优先级。 |
setpriority | 设置指定ID的静态优先级。 | ||
sched_rr_get_interval | 获取执行时间限制。 | - | |
sched_yield | 系统调用运行进程主动让出执行权。 | - | |
sched_get_priority_max | 获取进程静态优先级取值范围的最大值。 | 调度策略只支持:SCHED_FIFO 、SCHED_RR。 | |
sched_get_priority_min | 获取进程静态优先级取值范围的最小值。 | ||
sched_getscheduler | 获取调度策略。 | ||
sched_setscheduler | 设置调度策略。 | ||
sched_getparam | 获取调度参数。 | - | |
sched_setparam | 设置调度参数。 | - | |
exec | execl | 执行指定的elf格式的用户程序文件。 | - |
execle | 执行指定的elf格式的用户程序文件。 | - | |
execlp | 执行指定的elf格式的用户程序文件。 | - | |
execv | 执行指定的elf格式的用户程序文件。 | - | |
execve | 执行指定的elf格式的用户程序文件。 | - | |
execvp | 执行指定的elf格式的用户程序文件。 | - |
wait等待任意子进程结束并回收子进程资源。status的值可以由以下宏定义解析:
waitpid等待子进程结束并回收子进程资源。options:不支持WUNTRACED,WCONTINUED; status的值可以由以下宏定义解析:
调度getpriority获取指定ID的静态优先级。
setpriority设置指定ID的静态优先级。 sched_rr_get_interval获取执行时间限制。- sched_yield系统调用运行进程主动让出执行权。- sched_get_priority_max获取进程静态优先级取值范围的最大值。调度策略只支持:SCHED_FIFO 、SCHED_RR。 sched_get_priority_min获取进程静态优先级取值范围的最小值。 sched_getscheduler获取调度策略。 sched_setscheduler设置调度策略。 sched_getparam获取调度参数。- sched_setparam设置调度参数。- execexecl执行指定的elf格式的用户程序文件。-execle执行指定的elf格式的用户程序文件。- execlp执行指定的elf格式的用户程序文件。- execv执行指定的elf格式的用户程序文件。- execve执行指定的elf格式的用户程序文件。- execvp执行指定的elf格式的用户程序文件。-
二、线程
从系统的角度看,线程是竞争系统资源的最小运行单元。线程可以使用或等待CPU、使用内存空间等系统资源,并独立于其它线程运行。
OpenHarmony内核每个进程内的线程独立运行、独立调度,当前进程内线程的调度不受其它进程内线程的影响。
OpenHarmony内核中的线程采用抢占式调度机制,同时支持时间片轮转调度和FIFO调度方式。
OpenHarmony内核的线程一共有32个优先级(0-31),最高优先级为0,最低优先级为31。
当前进程内高优先级的线程可抢占当前进程内低优先级线程,当前进程内低优先级线程必须在当前进程内高优先级线程阻塞或结束后才能得到调度。
线程状态说明:
图 1 线程状态迁移示意图
线程状态迁移说明:
线程创建后,用户态可以执行线程调度、挂起、恢复、延时等操作,同时也可以设置线程优先级和调度策略,获取线程优先级和调度策略。
OpenHarmony内核系统中的线程管理模块,线程间通信为用户提供下面几种功能:
表 1 线程管理模块功能
头文件 | 名称 | 说明 | 备注 |
---|---|---|---|
pthread.h | pthread_attr_destroy | 销毁线程属性对象。 | - |
pthread.h | pthread_attr_getinheritsched | 获取线程属性对象的调度属性。 | - |
pthread.h | pthread_attr_getschedparam | 获取线程属性对象的调度参数属性。 | - |
pthread.h | pthread_attr_getschedpolicy | 获取线程属性对象的调度策略属性。 | OpenHarmony:支持SCHED_FIFO 、SCHED_RR调度策略。 |
pthread.h | pthread_attr_getstacksize | 获取线程属性对象的堆栈大小。 | - |
pthread.h | pthread_attr_init | 初始化线程属性对象。 | - |
pthread.h | pthread_attr_setdetachstate | 设置线程属性对象的分离状态。 | - |
pthread.h | pthread_attr_setinheritsched | 设置线程属性对象的继承调度属性。 | - |
pthread.h | pthread_attr_setschedparam | 设置线程属性对象的调度参数属性。 | OpenHarmony:设置线程优先级的参数值越小,线程在系统中的优先级越高;设置参数值越大,优先级越低。注意:需要将pthread_attr_t线程属性的inheritsched字段设置为PTHREAD_EXPLICIT_SCHED,否则设置的线程调度优先级将不会生效,系统默认设置为PTHREAD_INHERIT_SCHED。 |
pthread.h | pthread_attr_setschedpolicy | 设置线程属性对象的调度策略属性。 | OpenHarmony:支持SCHED_FIFO 、SCHED_RR调度策略。 |
pthread.h | pthread_attr_setstacksize | 设置线程属性对象的堆栈大小。 | - |
pthread.h | pthread_getattr_np | 获取已创建线程的属性。 | - |
pthread.h | pthread_cancel | 向线程发送取消请求。 | - |
pthread.h | pthread_testcancel | 请求交付任何未决的取请求。 | - |
pthread.h | pthread_setcanceltype | 设置线程可取消类型。 | - |
pthread.h | pthread_setcancelstate | 设置线程可取消状态。 | - |
pthread.h | pthread_create | 创建一个新的线程。 | - |
pthread.h | pthread_detach | 分离一个线程。 | - |
pthread.h | pthread_equal | 比较两个线程ID是否相等。 | - |
pthread.h | pthread_exit | 终止正在调用的线程。 | - |
pthread.h | pthread_getschedparam | 获取线程的调度策略和参数。 | OpenHarmony:支持SCHED_FIFO 、SCHED_RR调度策略。 |
pthread.h | pthread_join | 等待指定的线程结束。 | - |
pthread.h | pthread_self | 获取当前线程的ID。 | - |
pthread.h | pthread_setschedprio | 设置线程的调度静态优先级。 | - |
pthread.h | pthread_kill | 向线程发送信号。 | - |
pthread.h | pthread_once | 使函数调用只能执行一次。 | - |
pthread.h | pthread_atfork | 注册fork的处理程序。 | - |
pthread.h | pthread_cleanup_pop | 删除位于清理处理程序堆栈顶部的例程。 | - |
pthread.h | pthread_cleanup_push | 将例程推送到清理处理程序堆栈的顶部。 | - |
pthread.h | pthread_barrier_destroy | 销毁屏障对象(高级实时线程) | - |
pthread.h | pthread_barrier_init | 初始化屏障对象(高级实时线程) | - |
pthread.h | pthread_barrier_wait | 屏障同步(高级实时线程) | - |
pthread.h | pthread_barrierattr_destroy | 销毁屏障属性对象。 | - |
pthread.h | pthread_barrierattr_init | 初始化屏障属性对象。 | - |
pthread.h | pthread_mutex_destroy | 销毁互斥锁。 | - |
pthread.h | pthread_mutex_init | 初始化互斥锁。 | - |
pthread.h | pthread_mutex_lock | 互斥锁加锁操作。 | - |
pthread.h | pthread_mutex_trylock | 互斥锁尝试加锁操作。 | - |
pthread.h | pthread_mutex_unlock | 互斥锁解锁操作。 | - |
pthread.h | pthread_mutexattr_destroy | 销毁互斥锁属性对象。 | - |
pthread.h | pthread_mutexattr_gettype | 获取互斥锁类型属性。 | - |
pthread.h | pthread_mutexattr_init | 初始化互斥锁属性对象。 | - |
pthread.h | pthread_mutexattr_settype | 设置互斥锁类型属性。 | - |
pthread.h | pthread_mutex_timedlock | 使用超时锁定互斥锁。 | - |
pthread.h | pthread_rwlock_destroy | 销毁读写锁。 | - |
pthread.h | pthread_rwlock_init | 初始化读写锁。 | - |
pthread.h | pthread_rwlock_rdlock | 获取读写锁读锁操作。 | - |
pthread.h | pthread_rwlock_timedrdlock | 使用超时锁定读写锁读锁。 | - |
pthread.h | pthread_rwlock_timedwrlock | 使用超时锁定读写锁写锁。 | - |
pthread.h | pthread_rwlock_tryrdlock | 尝试获取读写锁读锁操作。 | - |
pthread.h | pthread_rwlock_trywrlock | 尝试获取读写锁写锁操作。 | - |
pthread.h | pthread_rwlock_unlock | 读写锁解锁操作。 | - |
pthread.h | pthread_rwlock_wrlock | 获取读写锁写锁操作。 | - |
pthread.h | pthread_rwlockattr_destroy | 销毁读写锁属性对象。 | - |
pthread.h | pthread_rwlockattr_init | 初始化读写锁属性对象。 | - |
pthread.h | pthread_cond_broadcast | 解除若干已被等待条件阻塞的线程。 | - |
pthread.h | pthread_cond_destroy | 销毁条件变量。 | - |
pthread.h | pthread_cond_init | 初始化条件变量。 | - |
pthread.h | pthread_cond_signal | 解除被阻塞的线程。 | - |
pthread.h | pthread_cond_timedwait | 定时等待条件。 | - |
pthread.h | pthread_cond_wait | 等待条件。 | - |
semaphore.h | sem_destroy | 销毁指定的无名信号量。 | - |
semaphore.h | sem_getvalue | 获得指定信号量计数值。 | - |
semaphore.h | sem_init | 创建并初始化一个无名信号量。 | - |
semaphore.h | sem_post | 增加信号量计数。 | - |
semaphore.h | sem_timedwait | 获取信号量,且有超时返回功能。 | - |
semaphore.h | sem_trywait | 尝试获取信号量。 | - |
semaphore.h | sem_wait | 获取信号量。 | - |
内存管理是开发过程中必须要关注的重要过程,它包括内存的分配、使用和回收。
良好的内存管理对于提高软件性能和可靠性有着十分重要的意义。
针对用户态开发,OpenHarmony内存提供了一套内存系统调用接口,支持内存的申请释放、重映射、内存属性的设置等,还有C库的标准内存操作函数。
表 1 标准C库相关接口
头文件 | 接口 | 功能 |
---|---|---|
strings.h | int bcmp(const void *s1, const void *s2, size_t n) | 比较字节序列。 |
strings.h | void bcopy(const void *src, void *dest, size_t n) | 拷贝字节序列。 |
strings.h | void bzero(void *s, size_t n) | 写入零值字节。 |
string.h | void *memccpy(void *dest, const void *src, int c, size_t n) | 拷贝src 所指的内存内容前n 个字节到dest 所指的地址上。复制时检查参数c 是否出现,若是则返回dest 中值为c 的下一个字节地址。 |
string.h | void *memchr(const void *s, int c, size_t n) | 在s所指内存的前n个字节中查找c。 |
string.h | int memcmp(const void *s1, const void *s2, size_t n) | 内存比较。 |
string.h | void *memcpy(void *dest, const void *src, size_t n) | 内存拷贝。 |
string.h | void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) | 找到一个子串。 |
string.h | void *memmove(void *dest, const void *src, size_t n) | 内存移动。 |
string.h | void *mempcpy(void *dest, const void *src, size_t n) | 拷贝内存区域。 |
string.h | void *memset(void *s, int c, size_t n) | 内存初始化。 |
stdlib.h | void *malloc(size_t size) | 申请内存。 |
stdlib.h | void *calloc(size_t nmemb, size_t size) | 申请内存并清零。 |
stdlib.h | void *realloc(void *ptr, size_t size) | 重分配内存。 |
stdlib.h/malloc. | void *valloc(size_t size) | 分配以页对齐的内存。 |
stdlib.h | void free(void *ptr) | 释放内存。 |
malloc.h | size_t malloc_usable_size(void *ptr) | 获取从堆分配的内存块的大小。 |
unistd.h | int getpagesize(void) | 获取页面大小。 |
unistd.h | void *sbrk(intptr_t increment) | 更改数据段大小。 |
差异接口详细说明:
说明: mmap与Linux实现差异详见与Linux标准库的差异章节。 返回值:
网络模块实现了TCP/IP协议栈基本功能,提供标准的POSIX socket接口。
说明: 当前系统使用lwIP提供网络能力。
针对用户态开发,OpenHarmony内核提供了一套网络功能系统调用接口,支持socket的创建关闭、数据收发、网络属性的设置等,通过C库提供标准的POSIX socket函数供开发者使用。
表 1 标准C库相关接口
头文件 | 接口 | 功能 |
---|---|---|
sys/socket.h | int accept(int socket, struct sockaddr *address, socklen_t *address_len) | 接受连接。 |
sys/socket.h | int bind(int s, const struct sockaddr *name, socklen_t namelen) | socket与IP地址绑定。 |
sys/socket.h | int shutdown(int socket, int how) | 关闭连接。 |
sys/socket.h | int getpeername(int s, struct sockaddr *name, socklen_t *namelen) | 获取对端地址。 |
sys/socket.h | int getsockname(int s, struct sockaddr *name, socklen_t *namelen) | 获取本地地址。 |
sys/socket.h | int getsockopt(int s, struct sockaddr *name, socklen_t *namelen) | 获取socket属性信息。 |
sys/socket.h | int setsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen) | 配置socket属性。 |
unistd.h | int close(int s) | 关闭socket。 |
sys/socket.h | int connect(int s, const struct sockaddr *name, socklen_t namelen) | 连接到指定的目的IP。 |
sys/socket.h | int listen(int sockfd, int backlog) | listen连接本socket的请求。 |
sys/socket.h | ssize_t recv(int socket, void *buffer, size_t length, int flags) | 接收socket上收到的数据。 |
sys/socket.h | ssize_t recvmsg(int s, struct msghdr *message, int flags) | 接收socket上收到的数据,可使用更丰富的参数。 |
sys/socket.h | ssize_t recvfrom(int socket, void *buffer, size_t length, int flags, struct sockaddr *address, socklen_t *address_len) | 接收socket上收到的数据,可同时获得数据来源IP地址。 |
sys/socket.h | ssize_t send(int s, const void *dataptr, size_t size, int flags) | 通过socket发送数据。 |
sys/socket.h | ssize_t sendmsg(int s, const struct msghdr *message, int flags) | 通过socket发送数据,可使用更丰富的参数。 |
sys/socket.h | ssize_t sendto(int s, const void *dataptr, size_t size, int flags, const struct sockaddr *to, socklen_t tolen) | 通过socket发送数据,可指定发送的目的IP地址。 |
sys/socket.h | int socket(int domain, int type, int protocol) | 创建socket。 |
sys/select.h | int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) | 多路复用。 |
sys/ioctl.h | int ioctl(int s, int request, ...) | socket属性获取、设置。 |
arpa/inet.h | const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) | 网络地址格式转换:将二进制格式IP地址转换为字符串格式。 |
arpa/inet.h | int inet_pton(int af, const char *src, void *dst) | 网络地址格式转换:将字符串格式IP地址转换为二进制格式。 |
与标准接口差异详细说明: