首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >php共享内存shmop遇到的坑

php共享内存shmop遇到的坑

原创
作者头像
云上冲浪者
修改2020-03-04 10:17:04
1.2K0
修改2020-03-04 10:17:04
举报
文章被收录于专栏:小文章小文章

本文讲述php共享内存shmop使用过程中遇到的问题和注意事项

维护某个后台PHP模块,发现有用到共享内存存储一些第三方的静态配置信息,使用共享内存过程中有遇到些问题,汇总在这里

1.shmop共享内存没有判断边界,超出限制会导致截断且未返回错误导致获取信息异常

shmop_write写入的数据,如果超出限制会自动截断而不报错:

看官网示例:

$written = shmop_write($shm_id, $write_d1, 0);
if ($written != strlen($write_d1)) {
   echo "failed\n";
} else {
   echo "ok\n";
}

结论:官网示例给出要求执行完写入操作后对写入数据进行判断,如果待写入的数据长度和实际数据长度不一致属于异常

2.遇到权限问题,导致写入共享内存失败

服务中遇到共享内存,很少会遇到权限的问题。

常见的权限问题为除了服务以外的监控/提醒脚本在部署的过程中因为权限和服务权限不一样导致权限问题(之前遇到脚本迁移或扩容的过程中因为部署权限问题导致共享内存读写失败的情况)。

因此,共享内存一定要注意权限的设置,shmop_open中有权限相关参数,需根据不同场景来进行设置:

维护某个后台PHP模块,发现有用到共享内存存储一些第三方的静态配置信息,使用共享内存过程中有遇到些问题,汇总在这里

1.shmop共享内存没有判断边界,超出限制会导致截断且未返回错误导致获取信息异常

shmop_write写入的数据,如果超出限制会自动截断而不报错:

看官网示例:

$written = shmop_write($shm_id, $write_d1, 0);
if ($written != strlen($write_d1)) {
   echo "failed\n";
} else {
   echo "ok\n";
}

结论:官网示例给出要求执行完写入操作后对写入数据进行判断,如果待写入的数据长度和实际数据长度不一致属于异常

2.遇到权限问题,导致写入共享内存失败

服务中遇到共享内存,很少会遇到权限的问题。

常见的权限问题为除了服务以外的监控/提醒脚本在部署的过程中因为权限和服务权限不一样导致权限问题(之前遇到脚本迁移或扩容的过程中因为部署权限问题导致共享内存读写失败的情况)。

因此,共享内存一定要注意权限的设置,shmop_open中有权限相关参数,需根据不同场景来进行设置:

共享内存信息查看
共享内存信息查看

结论:同一机器上需保持读写同一片共享内存的权限一致

3.ftok函数获取系统共享内存唯一编号key_t,虽然pathname和proj不变,key_t也可能会变化,偶尔发现什么数据也没改动共享内存数据为空了

key_t = ftok ( string $pathname , string $proj )

ftok获取的健值是由ftok函数的第二个参数的后8位,st_dev的后8位,st_ino的后16位构成的:

char filename[50];
 struct stat buf;
 int ret;
 strcpy( filename, "/home/satellite/" );
 ret = stat( filename, &buf );
 if( ret )
 {
 printf( "stat error\n" );
 return -1;
 }

 printf( "the file info: ftok( filename, 0x27 ) = %x, st_ino = %x, st_dev= %x\n", ftok( filename, 0x27 ), buf.st_ino, buf.st_dev );

stat数据结构如下,可通过stat命令查看文件详细信息:

The structure stat contains at least the following members:
dev_t     st_dev     ID of device containing file
ino_t     st_ino     file serial number
mode_t    st_mode    mode of file (see below)
nlink_t   st_nlink   number of links to the file
uid_t     st_uid     user ID of file
gid_t     st_gid     group ID of file
dev_t     st_rdev    device ID (if file is character or block special)
off_t     st_size    file size in bytes (if file is a regular file)
time_t    st_atime   time of last access
time_t    st_mtime   time of last data modification
time_t    st_ctime   time of last status change
blksize_t st_blksize a filesystem-specific preferred I/O block size for
                     this object.  In some filesystem types, this may
                     vary from file to file
blkcnt_t  st_blocks  number of blocks allocated for this object

可以看出即使pathname和proj 不变,只要文件修改或删除,st_dev st_ino发生变化key_t也有可能发生变化:

可以通过stat -c '%i' filename 查看i节点,

通过stat -c '%d' filename 查看文件设备编号,

这里在获取ID的时候要注意,有时发现什么也没改动,查询共享内存数据无缘无故消失了,可能就是修改或删除filename的文件导致。

结论:只要文件发生变更,哪怕入参不变key_t也可能会变化,如果我们遇到没有变动任何代码,共享内存却为空了,可以通过上述方式排查。

参考资料

https://pubs.opengroup.org/onlinepubs/009695399/basedefs/sys/stat.h.html

https://pubs.opengroup.org/onlinepubs/007908799/xsh/sysstat.h.html

结论:同一机器上需保持读写同一片共享内存的权限一致

3.ftok函数获取系统共享内存唯一编号key_t,虽然pathname和proj不变,key_t也可能会变化,偶尔发现什么数据也没改动共享内存数据为空了

key_t = ftok ( string $pathname , string $proj )

ftok获取的健值是由ftok函数的第二个参数的后8位,st_dev的后8位,st_ino的后16位构成的:

char filename[50];
 struct stat buf;
 int ret;
 strcpy( filename, "/home/satellite/" );
 ret = stat( filename, &buf );
 if( ret )
 {
 printf( "stat error\n" );
 return -1;
 }

 printf( "the file info: ftok( filename, 0x27 ) = %x, st_ino = %x, st_dev= %x\n", ftok( filename, 0x27 ), buf.st_ino, buf.st_dev );

stat数据结构如下,可通过stat命令查看文件详细信息:

The structure stat contains at least the following members:
dev_t     st_dev     ID of device containing file
ino_t     st_ino     file serial number
mode_t    st_mode    mode of file (see below)
nlink_t   st_nlink   number of links to the file
uid_t     st_uid     user ID of file
gid_t     st_gid     group ID of file
dev_t     st_rdev    device ID (if file is character or block special)
off_t     st_size    file size in bytes (if file is a regular file)
time_t    st_atime   time of last access
time_t    st_mtime   time of last data modification
time_t    st_ctime   time of last status change
blksize_t st_blksize a filesystem-specific preferred I/O block size for
                     this object.  In some filesystem types, this may
                     vary from file to file
blkcnt_t  st_blocks  number of blocks allocated for this object

可以看出即使pathname和proj 不变,只要文件修改或删除,st_dev st_ino发生变化key_t也有可能发生变化:

可以通过stat -c '%i' filename 查看i节点,

通过stat -c '%d' filename 查看文件设备编号,

这里在获取ID的时候要注意,有时发现什么也没改动,查询共享内存数据无缘无故消失了,可能就是修改或删除filename的文件导致。

结论:只要文件发生变更,哪怕入参不变key_t也可能会变化,如果我们遇到没有变动任何代码,共享内存却为空了,可以通过上述方式排查。

参考资料

https://pubs.opengroup.org/onlinepubs/009695399/basedefs/sys/stat.h.html

https://pubs.opengroup.org/onlinepubs/007908799/xsh/sysstat.h.html

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档