[20261001]oracle Semaphore Arrays Key值的计算.txt

[20261001]oracle Semaphore Arrays Key值的计算.txt

--//尝试计算ipcs -s输出的Semaphore Arrays Key值的计算。

1.问题提出:
--//关闭数据库重新启动:
--//修改/etc/sudoers建立加入如下:
# grep oracle /etc/sudoers
oracle  ALL=(ALL)       ALL

--//采用如下方式执行,sqlplus使用全路径,并且使用sys用户以及口令。
$ mkdir strace ; cd strace
$ sudo -E strace -ff -o nnnn -Ttt -y /u01/app/oracle/product/21.0.0/dbhome_1/bin/sqlplus -s -l sys/bookbook as sysdba <<<"startup"

$ ipcs -a
------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x00000000 0          oracle     600        10485760   58
0x00000000 1          oracle     600        1140850688 58
0x00000000 2          oracle     600        8388608    58
0xafa94c20 3          oracle     600        2097152    58

------ Semaphore Arrays --------
key        semid      owner      perms      nsems
0x5507207c 3          oracle     600        250
--//Semaphore Arrays key=0x5507207c.

2.扫描跟踪文件:
$ grep -i 5507207c *
nnnn.2651:10:00:02.004806 semget(0x5507207c, 0, 000) = -1 ENOENT (No such file or directory) <0.000040>
nnnn.2651:10:00:02.005599 semget(0x5507207c, 250, IPC_CREAT|IPC_EXCL|0600) = 3 <0.000051>

$ grep semget nnnn.2651
10:00:01.999855 semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL|0600) = 0 <0.000554>
10:00:02.003860 semget(IPC_PRIVATE, 250, IPC_CREAT|IPC_EXCL|0666) = 1 <0.000051>
10:00:02.004371 semget(IPC_PRIVATE, 250, IPC_CREAT|0660) = 2 <0.000051>
10:00:02.004806 semget(0x5507207c, 0, 000) = -1 ENOENT (No such file or directory) <0.000040>
10:00:02.004923 semget(0x7e0edb60, 0, 000) = -1 ENOENT (No such file or directory) <0.000038>
10:00:02.005033 semget(0x99eaaedc, 0, 000) = -1 ENOENT (No such file or directory) <0.000044>
10:00:02.005189 semget(0x32fcf5bc, 0, 000) = -1 ENOENT (No such file or directory) <0.000087>
10:00:02.005599 semget(0x5507207c, 250, IPC_CREAT|IPC_EXCL|0600) = 3 <0.000051>
--//semget执行4次参数1选择不同的值。
--//另外出现semget(0x7e0edb60, 0, 000),semget(0x99eaaedc, 0, 000),semget(0x32fcf5bc, 0, 000),猜测避免冲突做的尝试。
--//不知道oracle实例启动为什么这样设计,尝试4种键值,只要semget(0x5507207c, 0, 000) = -1就没有使用,直接执行
--//semget(0x5507207c, 250, IPC_CREAT|IPC_EXCL|0600) 不就可以了吗?

--//继续查看跟踪文件内容:
10:00:02.005599 semget(0x5507207c, 250, IPC_CREAT|IPC_EXCL|0600) = 3 <0.000051>
--//返回3对应 semid,250对应oracle processes参数+4=246+4=250。
SYS@book> @ hidez ^processes$
 NUM N_HEX  CON_ID NAME      DESCRIPTION    DEFAULT_VALUE SESSION_VALUE SYSTEM_VALUE ISSES_MODIFIABL ISSYS_MODIFIABLE
---- ------ ------ --------- -------------- ------------- ------------- ------------ --------------- ---------------------------
  52    34       0 processes user processes FALSE         246           246          FALSE           IMMEDIATE

10:00:02.005724 semctl(3, 1, SETVAL, 0x43fd) = 0 <0.000049>
10:00:02.005846 semctl(3, 2, SETVAL, 0x64df) = 0 <0.000049>
10:00:02.005993 semctl(3, 3, SETVAL, 0x7ff9) = 0 <0.000044>
10:00:02.006137 semctl(3, 0, SETVAL, 0x8000000000) = 0 <0.000045>
--//这样很清楚跟踪启动时执行semget系统调用设置Semaphore Arrays key值。
--//设置这些值不是很清楚:
$ ipcs -s -i 3 | head -13 ;  ipcs -s -i 3 | tail -4
Semaphore Array semid=3
uid=54321        gid=54321       cuid=54321      cgid=54321
mode=0600, access_perms=0600
nsems = 250
otime = Tue Oct  6 15:30:43 2026
ctime = Tue Oct  6 15:30:34 2026
semnum     value      ncount     zcount     pid
0          0          0          0          2882
1          17405      0          0          2882
2          25823      0          0          2882
3          32761      0          0          2882
4          0          0          0          0
247        0          0          0          0
248        0          0          0          0
249        0          0          0          2882
--//17405 = 0x43fd
--//25823 = 0x64df
--//32761 = 0x7ff9

3.看看oracle启动实例调用semget时的堆栈:
$ mkdir mmmm; cd mmmm
//$ sudo -E strace -ff -o mmmm  -k --stack-trace-frame-limit=5 -e semget -Ttt -y /u01/app/oracle/product/21.0.0/dbhome_1/bin/sqlplus -s -l sys/bookbook as sysdba <<<"startup nomount"
$ sudo -E strace -ff -o mmmm  -k --stack-trace-frame-limit=5 -e semget -Ttt -y /u01/app/oracle/product/21.0.0/dbhome_1/bin/sqlplus -s -l sys/bookbook as sysdba <<<"startup "

--//执行startup nomount
$ grep -A4 "semget(0x5507207c" mmmm.*
mmmm.3859:10:53:47.531621 semget(0x5507207c, 0, 000) = -1 ENOENT (No such file or directory) <0.000089>
mmmm.3859- > /usr/lib64/libc.so.6(semget+0xb) [0x111bcb]
mmmm.3859- > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(sskgpremovesem+0x45) [0x57b64d5]
mmmm.3859- > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(ksunfy+0xb8c) [0x148f54c]
mmmm.3859- > too many stack frames
--
mmmm.3859:10:53:47.548053 semget(0x5507207c, 250, IPC_CREAT|IPC_EXCL|0600) = 23 <0.000078>
mmmm.3859- > /usr/lib64/libc.so.6(semget+0xb) [0x111bcb]
mmmm.3859- > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(sskgpcreatesem+0x67) [0x57b6637]
mmmm.3859- > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(ksunfy+0xb8c) [0x148f54c]
mmmm.3859- > too many stack frames

--//执行startup
$ grep -A6 "semget(0x5507207c" mmmm.*
mmmm.4760:11:24:37.227107 semget(0x5507207c, 0, 000) = -1 ENOENT (No such file or directory) <0.000055>
mmmm.4760- > /usr/lib64/libc.so.6(semget+0xb) [0x111bcb]
mmmm.4760- > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(sskgpremovesem+0x45) [0x57b64d5]
mmmm.4760- > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(sskgpwcr+0x316) [0x57b5506]
mmmm.4760- > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(skgpwinit+0x345) [0x5785175]
mmmm.4760- > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(ksunfy+0xb8c) [0x148f54c]
mmmm.4760- > too many stack frames
--
mmmm.4760:11:24:37.250704 semget(0x5507207c, 250, IPC_CREAT|IPC_EXCL|0600) = 27 <0.000069>
mmmm.4760- > /usr/lib64/libc.so.6(semget+0xb) [0x111bcb]
mmmm.4760- > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(sskgpcreatesem+0x67) [0x57b6637]
mmmm.4760- > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(sskgpwcr+0x348) [0x57b5538]
mmmm.4760- > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(skgpwinit+0x345) [0x5785175]
mmmm.4760- > /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle(ksunfy+0xb8c) [0x148f54c]
mmmm.4760- > too many stack frames
--//执行startup nomount 时 漏了2个函数sskgpwcr,skgpwinit,不知道为什么,而且每次执行都是--stack-trace-frame-limit=5。

$ objdump -d --disassemble=sskgpwcr /u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle| grep callq | grep -o "<.*>" | sort | uniq | tee a3.txt
<skgoprint>
<slosFillErr>
<sscanf>
<sskgpcreatesem>
<sskgp_fthread_ipc_instance_create_fp>
<sskgpfthrinit>
<sskgphpjw>
<sskgpremovesem>
<sskgpsemspersemid>
<sskgpwfindops>
<sskgpwidtokeys>
<uname@plt>

--//利用vim编辑形成如下文件:
$ cat test6.bt
uretprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:skgoprint
uretprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:slosFillErr
uretprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:sscanf
uretprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:sskgpcreatesem
uretprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:sskgpfthrinit
uretprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:sskgphpjw
uretprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:sskgpremovesem
uretprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:sskgpsemspersemid
uretprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:sskgpwfindops
uretprobe:/u01/app/oracle/product/21.0.0/dbhome_1/bin/oracle:sskgpwidtokeys
/ $1 == 0 || pid == $1 /
{
    printf("[%s] %s pid=%d return hash_value=%016lx %lu\n", strftime("%H:%M:%S", nsecs), func,pid, retval, retval);
}

--//注:删除sskgp_fthread_ipc_instance_create_fp(主要原因执行bpftrace脚本报错),<uname@plt>(可以排除)。
--//关闭数据库重新启动实例:
# bpftrace  test6.bt 0
....
[11:36:43] skgoprint pid=5146 return hash_value=000000000000002d 45
[11:36:43] sskgphpjw pid=5146 return hash_value=000000005507207c 1426530428
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[11:36:43] sskgphpjw pid=5146 return hash_value=000000007e0edb60 2114902880
[11:36:43] sskgphpjw pid=5146 return hash_value=0000000099eaaedc 2582294236
[11:36:43] sskgphpjw pid=5146 return hash_value=0000000032fcf5bc 855438780
[11:36:43] sskgpwidtokeys pid=5146 return hash_value=0000000000000001 1
[11:36:43] sscanf pid=5146 return hash_value=0000000000000003 3
[11:36:43] sskgpsemspersemid pid=5146 return hash_value=00000000000000fa 250
[11:36:43] sskgpwfindops pid=5146 return hash_value=00000000000000fa 250
[11:36:43] sskgpremovesem pid=5146 return hash_value=000000005507207c 1426530428
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[11:36:43] sskgpcreatesem pid=5146 return hash_value=0000000000000001 1
[11:36:43] skgoprint pid=5146 return hash_value=000000000000000e 14
--//注:hash_value输出的16进制值前面少写了0x,不影响后面的分析.

--//显示输出信息非常快并且很多,直接按ctrl+c中断,可以注解一些函数的返回,特别是skgoprint,slosFillErr,sscanf,sskgpfthrinit。
--//查询5507207c,发现2处的返回出现000000005507207c,sskgpremovesem函数可以排除,应该是删除时的返回值。
--//可以推断计算Semaphore Arrays Key就是使用sskgphpjw函数。另外000000007e0edb60,0000000099eaaedc,0000000032fcf5bc的出
--//现与前面grep semget nnnn.2651的输出也验证我的判断。

--//到此已经基本确定使用sskgphpjw函数计算Semaphore Arrays Key。

--//避免写太长,另外写一篇blog继续后面的分析。
--//后记:幸亏sskgpwcr函数存在sskgphpjw函数的调用,不要估计定位又要花费大量的时间。

posted @ 2026-10-06 21:05  lfree  阅读(3)  评论(0)    收藏  举报