3 进程与线程实例
进程是操作系统分配资源的单位,而线程是操作系统调度的单位。
这是一句很值得琢磨的话。比如,多核CPU是否一定能加快程序的运行呢?操作系统怎样才能把多核利用上?这就是操作系统调度相关的问题,只有程序是多线程结构的,才可能被同时被调度执行,从而利用多核实现并行。
我们研究一下两个著名的开源数据库系统,看看它们的结构是如何实现的。一个系统是进程结构还是线程结构,可以通过搜索创建进程或线程的函数来初步确认。
3.1 多进程结构的大型数据库管理系统――PostgreSQL
在PostgreSQL中我们通过搜索CreateProcess等函数可以知晓,PostgreSQL是多进程结构。
表1-Windows系统下涉及的函数
搜索的函数 | 涉及的文件 | 功能分析 |
_beginthreadex | src\backend\postmaster\Syslogger.c | 系统日志进程调用的输出相关的局部功能 |
src\interfaces\ecpg\test\expected目录下 Thread-alloc.c Thread-descriptor.c Thread-prep.c | 测试相关,不涉及数据库服务器的结构 | |
_beginthread | 无 |
|
CreateThread | src\backend\postmaster\postmaster.c | 只对windows系统增加一个辅助的信号等待线程 |
src\backend\port\win32\signal.c | 在windows上通过有名管道处理信号处理 | |
src\interfaces\ecpg\test\expected\ thread-thread.c | 测试相关,不涉及数据库服务器的结构 | |
src\interfaces\ecpg\test\expected\ Thread-thread_implicit.c | ||
src\backend\port\win32\timer.c | 在windows模拟一个定时器(setitimer) | |
CreateProcess | src\port\Exec.c | 被pipe_read_line函数调用,只涉及局部读管道操作 |
src\bin\pg_ctl\Pg_ctl.c | 独立的控制程序,非服务器相关代码 | |
src\backend\postmaster\Postmaster.c | 数据库服务器主进程。 internal_forkexec调用CreateProcess internal_forkexec被调用关系如“图2-internal_forkexec函数调用关系图”。由此可以深入追踪,进而探知PG的多进程结构。另外,可以关注“fork_process”函数。 |
表2-Linux系统下涉及的函数
搜索的函数 | 涉及的文件 | 功能分析 |
pthread_create | src\interfaces\ecpg\test\expecte目录下 Thread-alloc.c Thread-descriptor.c Thread-prep.c Thread-thread.c Thread-thread_implicit.c | 测试相关,不涉及数据库服务器的结构 |
src\test\thread\Thread_test.c | ||
fork | src\backend\postmaster\ Fork_process.c | fork_process调用fork fork_process被调用关系如下: fork_process StartAutoVacLauncher StartAutoVacWorker pgarch_start pgstat_start pmdaemonize internal_forkexec SysLogger_Start |
src\backend\port\Ipc_test.c | 测试相关,不涉及数据库服务器的结构 | |
src\test\regress\Pg_regress.c | Pg_regress.c是回归测试代码。测试相关,不涉及数据库服务器的结构 | |
src\backend\port\darwin\System.c | 屏蔽平台差异的system函数调用fork |
从上述两表可以看出,PostgreSQL和线程基本没有关系,只是局部的代码因操作系统平台不同使用了程序,而数据库服务器引擎的主要部分postmaster没有使用线程,而是通过internal_forkexec调用fork函数创建了诸多相关进程。可见其隶属于多进程结构。