Android | AOSP | 知识扩展
Android | AOSP | 知识扩展
td::optional
std::optional
是 C++17 中引入的一种容器,用于表示一个可能不存在的对象。其类模板的定义如下:
template <typename T>
class optional {
public:
optional(); // 构造函数,创建一个空的 optional 对象
optional(const T& value); // 构造函数,创建一个存放了 value 值的 optional 对象
optional& operator=(const T& value); // 赋值运算符,将 value 赋值给 optional 对象
T& operator*(); // 返回存储在 optional 对象中的值的引用
const T& operator*() const; // 返回存储在 optional 对象中的值的 const 引用
T* operator->(); // 返回存储在 optional 对象中的值的指针
const T* operator->() const; // 返回存储在 optional 对象中的值的 const 指针
explicit operator bool() const; // 检查 optional 对象是否包含一个值
T& value(); // 返回存储在 optional 对象中的值的引用,如果对象为空则抛出 std::bad_optional_access 异常
const T& value() const; // 返回存储在 optional 对象中的值的 const 引用,如果对象为空则抛出 std::bad_optional_access 异常
};
std::optional
可以用来避免在代码中使用空指针或无效引用,从而降低代码出错的可能性。在某些情况下,我们需要一个变量可能存在或不存在,这时就可以使用 std::optional
来表示这种可能性。例如:
std::optional<int> num; // 创建一个空的 optional 对象
num = 42; // 将 42 赋值给 optional 对象
if (num) { // 检查 optional 对象是否包含一个值
std::cout << "num is " << *num << std::endl; // 访问存储在 optional 对象中的值
} else {
std::cout << "num is not set" << std::endl;
}
在上面的例子中,我们使用 std::optional
来表示一个整数变量可能存在或不存在的情况。如果 optional 对象包含一个值,则通过解引用操作符 *
来访问该值。否则,我们可以通过检查对象是否包含值来避免访问未定义的内存。
std::optional 中 emplace
template <class... _Args,
class = enable_if_t
<
is_constructible_v<value_type, _Args...>
>
>
_LIBCPP_INLINE_VISIBILITY
_Tp &
emplace(_Args&&... __args)
{
reset();
this->__construct(_VSTD::forward<_Args>(__args)...);
return this->__get();
}
这段代码是std::optional
中emplace
成员函数的模板实现。emplace
函数的主要作用是在std::optional
对象中构造一个新的值,使用传入的参数作为构造函数的参数。
// 定义emplace成员函数模板
template <class... _Args,
class = enable_if_t
<
is_constructible_v<value_type, _Args...>
>
>
// 设置内联可见性,使得编译器可以在编译时优化函数调用
_LIBCPP_INLINE_VISIBILITY
// 定义emplace函数,返回值类型为模板参数_Tp的引用,接受可变数量的模板参数_Args
_Tp &
emplace(_Args&&... __args)
{
// 调用reset()函数,清除optional对象当前的值,为新值做好准备
reset();
// 使用完美转发将传入的参数列表(__args)转发给构造函数
this->__construct(_VSTD::forward<_Args>(__args)...);
// 返回新构造值的引用
return this->__get();
}
emplace
函数首先调用reset()
方法清除std::optional
对象中的当前值。接下来,使用完美转发将传入的参数列表(__args
)转发给value_type
的构造函数,value_type
是存储在std::optional
中的类型。最后,返回新构造值的引用。
sys_nanosleep
sys_nanosleep
是一个操作系统内核系统调用,它用于暂停当前进程一段指定的时间。在Linux系统中,这个系统调用的原型如下:
#include <time.h>
int sys_nanosleep(const struct timespec *req, struct timespec *rem);
第一个参数req
是一个指向timespec
结构体的指针,表示要暂停的时间长度。该结构体包含两个成员变量,分别为tv_sec
和tv_nsec
,分别表示秒数和纳秒数。第二个参数rem
是一个指向timespec
结构体的指针,表示剩余未暂停的时间长度。如果在暂停的过程中被信号打断,那么rem
将会被设置为剩余未暂停的时间。
sys_nanosleep
的返回值为0表示暂停成功,返回-1表示暂停失败,错误码保存在errno
中。
sys_ioctl
sys_ioctl
是一个操作系统内核系统调用,用于操作设备文件的I/O控制。在Linux系统中,这个系统调用的原型如下:
#include <sys/ioctl.h>
int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
第一个参数fd
是一个整数类型,表示要进行I/O控制的设备文件描述符。第二个参数cmd
是一个无符号整数类型,表示要进行的I/O操作,通常是一个预定义的常量。第三个参数arg
是一个无符号长整型,表示I/O操作的参数,可以是一个指针或一个整数。
不同的设备文件可能支持不同的I/O操作,因此cmd
参数的含义也不同。例如,对于网络设备文件,可能有SIOCGIFADDR
操作,用于获取设备的IP地址;对于串口设备文件,可能有TCGETS
操作,用于获取串口的配置信息。
sys_ioctl
的返回值为0表示I/O操作成功,返回-1表示I/O操作失败,错误码保存在errno
中。
Android init 脚本
Android init 脚本是一种 Android 系统启动时用于配置和启动各种服务、设置属性和创建目录等操作的脚本。它们主要用于定义系统的启动流程和配置各种组件。这些脚本通常位于 Android 源码中的各个子项目和设备特定代码中,如 system/core/rootdir
、device/<manufacturer>/<device>/rootdir
等。
Android init 脚本的作用包括:
- 设置系统属性:用于配置系统行为、开关和设备特性等。
- 创建目录和文件:用于在启动过程中创建必要的目录结构和文件。
- 设置权限:用于设定系统目录和文件的访问权限,以确保正确的访问控制。
- 启动服务:用于配置和启动系统中的各种守护进程和服务。
Android init 脚本使用一种名为 init
的简单语言编写,该语言包含一系列命令和关键字,用于表示不同的操作。例如:
service
:定义一个服务,包括服务名、可执行文件路径和相关参数。on
:定义在特定事件触发时要执行的操作。setprop
:设置系统属性。mkdir
:创建目录。chmod
:更改文件或目录权限。
要使用 Android init 脚本,您需要:
- 在 Android 源码中找到相关的 init 脚本,如
init.rc
、init.<device>.rc
或设备特定的 init 脚本。 - 阅读和理解脚本中的命令和关键字,以及它们在系统启动过程中的作用。
- 修改或添加 init 脚本中的命令和关键字,以满足您的需求。
- 编译并刷入新的 Android 系统映像,然后观察更改后的系统行为。
Android.bp的作用
Android.bp
是 Android 开源项目 (AOSP) 中的一种构建脚本,它使用类似 Makefile 的语法来描述如何构建 Android 应用程序、库和模块。它是 AOSP 中使用的 Soong 构建系统的核心组件之一,是 Android 7.0 及更高版本中用于构建的主要构建系统。
Android.bp
文件中描述了一个模块的依赖关系、编译选项、源代码文件列表等信息,构建系统将基于这些信息来生成构建脚本和构建产物。相比于之前使用的 GNU Make 工具链,Soong 构建系统更加灵活、可扩展和高效,能够更好地支持 Android 平台的复杂构建需求。
在 Android 源代码中,每个模块都有一个相应的 Android.bp
文件,用于描述该模块的构建规则。这些模块包括 Android 系统本身、应用程序、共享库、静态库、插件等。开发者可以修改这些 Android.bp
文件来增加、删除或修改模块的构建规则,以满足自己的需求。
总之,Android.bp
文件是 AOSP 中描述如何构建 Android 应用程序、库和模块的核心文件,它是 Soong 构建系统的核心组件之一。
emplace
https://en.cppreference.com/w/cpp/utility/optional/emplace
emplace_back
https://en.cppreference.com/w/cpp/container/vector/emplace_back
surfaceflinger
service surfaceflinger /system/bin/surfaceflinger class core animation user system group graphics drmrpc readproc capabilities SYS_NICE onrestart restart --only-if-running zygote task_profiles HighPerformance socket pdx/system/vr/display/client stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0 socket pdx/system/vr/display/manager stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0 socket pdx/system/vr/display/vsync stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0
surfaceflinger.rc
是一个 Android init 脚本,用于定义 SurfaceFlinger 服务的配置。SurfaceFlinger 是 Android 系统的核心组件,负责合成和显示图形。该文件定义了 SurfaceFlinger 服务的启动方式和权限。现在让我们分析文件的每一行内容:
service surfaceflinger /system/bin/surfaceflinger
定义一个名为 "surfaceflinger" 的服务,它的可执行文件位于/system/bin/surfaceflinger
。class core animation
将 SurfaceFlinger 服务分配到 "core" 和 "animation" 类别。这些类别用于在特定条件下控制服务的启动和关闭。user system
设置 SurfaceFlinger 服务运行在 "system" 用户上下文中。group graphics drmrpc readproc
将 SurfaceFlinger 服务的组设置为 "graphics"、"drmrpc" 和 "readproc"。这些组定义了服务的权限。capabilities SYS_NICE
赋予 SurfaceFlinger 服务 SYS_NICE 功能。这允许服务更改其调度优先级,以便在需要时获得更多 CPU 时间。onrestart restart --only-if-running zygote
如果 SurfaceFlinger 服务重启,该行命令会尝试重启名为 "zygote" 的服务。--only-if-running
参数确保仅在 "zygote" 服务已运行时执行重启操作。task_profiles HighPerformance
为 SurfaceFlinger 服务分配 "HighPerformance" 任务配置文件。这可能会调整服务的性能参数。
8-10. socket pdx/...
这三行定义了 SurfaceFlinger 服务用于与客户端通信的 UNIX 域套接字。套接字的权限、所有者和安全上下文在这些行中定义。
总之,surfaceflinger.rc
文件定义了 SurfaceFlinger 服务的启动配置、权限和通信方式。这个文件在 Android 系统启动时被 init 进程读取,用于正确地启动和运行 SurfaceFlinger 服务。