package shm import ( "fmt" "unsafe" "config-loader/internal/constants" "config-loader/internal/logger" "config-loader/internal/models" "golang.org/x/sys/unix" ) // shmget 调用系统调用 SYS_SHMGET 创建或获取共享内存段 // key: 共享内存的键值 // size: 共享内存的大小 // shmflg: 标志位,用于指定权限和行为 func shmget(key int, size int, shmflg int) (int, error) { id, _, errno := unix.Syscall(unix.SYS_SHMGET, uintptr(key), uintptr(size), uintptr(shmflg)) if errno != 0 { return 0, errno } return int(id), nil } // shmat 调用系统调用 SYS_SHMAT 将共享内存段附加到进程的地址空间 // shmid: 共享内存段的 ID // shmaddr: 指定的附加地址(通常为 0 表示系统自动选择) // shmflg: 标志位,用于指定附加模式 func shmat(shmid int, shmaddr uintptr, shmflg int) (unsafe.Pointer, error) { addr, _, errno := unix.Syscall(unix.SYS_SHMAT, uintptr(shmid), shmaddr, uintptr(shmflg)) if errno != 0 { return nil, errno } return unsafe.Pointer(addr), nil } // shmdt 调用系统调用 SYS_SHMDT 将共享内存段从进程的地址空间分离 // shmaddr: 共享内存段的地址 func shmdt(shmaddr unsafe.Pointer) error { _, _, errno := unix.Syscall(unix.SYS_SHMDT, uintptr(shmaddr), 0, 0) if errno != 0 { return errno } return nil } // WriteConfigToSharedMemory 将配置数据写入共享内存 // config: 要写入的配置数据 func WriteConfigToSharedMemory(config *models.ConfigData) error { logger.DebugLogger.Println("Starting to write configuration to shared memory") // 创建或获取共享内存段 shmID, err := shmget(constants.ShmKey, constants.ShmSize, unix.IPC_CREAT|0666) if err != nil { logger.ErrorLogger.Printf("shmget failed: %v", err) return fmt.Errorf("shmget failed: %w", err) } // 将共享内存段附加到进程地址空间 shmPtr, err := shmat(shmID, 0, 0) if err != nil { logger.ErrorLogger.Printf("shmat failed: %v", err) return fmt.Errorf("shmat failed: %w", err) } defer shmdt(shmPtr) // 确保在函数结束时分离共享内存 // 检查配置数据大小是否超过共享内存大小 configSize := unsafe.Sizeof(*config) if configSize > constants.ShmSize { return fmt.Errorf("configuration size (%d) exceeds shared memory size (%d)", configSize, constants.ShmSize) } // 将配置数据复制到共享内存 data := (*[constants.ShmSize]byte)(unsafe.Pointer(config))[:] copy((*[constants.ShmSize]byte)(shmPtr)[:], data) logger.InfoLogger.Println("Configuration successfully written to shared memory") return nil } // ReadConfigFromSharedMemory 从共享内存读取配置数据 func ReadConfigFromSharedMemory() (*models.ConfigData, error) { logger.DebugLogger.Println("Starting to read configuration from shared memory") // 获取共享内存段 shmID, err := shmget(constants.ShmKey, constants.ShmSize, 0) if err != nil { return nil, fmt.Errorf("shmget failed: %w", err) } // 将共享内存段附加到进程地址空间(只读模式) shmPtr, err := shmat(shmID, 0, unix.SHM_RDONLY) if err != nil { return nil, fmt.Errorf("shmat failed: %w", err) } defer shmdt(shmPtr) // 确保在函数结束时分离共享内存 // 创建一个新的配置数据对象 config := new(models.ConfigData) configSize := unsafe.Sizeof(*config) if configSize > constants.ShmSize { return nil, fmt.Errorf("configuration size (%d) exceeds shared memory size (%d)", configSize, constants.ShmSize) } // 从共享内存复制数据到配置对象 copy((*[constants.ShmSize]byte)(unsafe.Pointer(config))[:], (*[constants.ShmSize]byte)(shmPtr)[:]) logger.InfoLogger.Println("Configuration successfully read from shared memory") return config, nil }