You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux下使用JNA调用POSIX信号量报错22(无效参数)求助

解决JNA调用POSIX信号量sem_post返回EINVAL(错误码22)的问题

我一眼就看到几个关键问题导致了你遇到的无效参数错误,咱们一步步拆解并修复:

1. 最大的问题:错误地把普通文件路径当成POSIX信号量名字

POSIX信号量是IPC(进程间通信)对象,不是文件系统里的普通文件!你手动创建/tmp/_testXXX文件的操作完全是多余的,甚至会干扰sem_open的正常工作:

  • sem_open 要求信号量名字必须以 / 开头,且名字里不能包含其他斜杠(比如/my_test_sem是合法的,/tmp/my_sem就不行)
  • 当你用一个已经存在的普通文件路径去调用sem_open,系统会无法识别为信号量对象,直接返回无效指针,后续调用sem_post自然会报EINVAL。

2. 没有检查sem_open的返回值

sem_open失败时会返回SEM_FAILED(对应JNA的Pointer.NULL),你直接跳过检查就调用sem_post,相当于给无效指针发指令,不出错才怪。一定要先判断返回值是否有效。

3. 权限参数的进制错误

你写的666是十进制,但POSIX权限需要用八进制,十进制666转换成八进制是1232,这完全不是你想要的读写权限,应该写成0666(Java里八进制数字以0开头)。

4. 可选优化:用JNA内置常量代替手动定义

你手动定义的O_CREAT = 0x40虽然数值正确,但JNA的jna-platform库已经提供了Fcntl.O_CREAT常量,直接用可以避免手动定义出错的风险。


修复后的完整代码

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.unix.fcntl.Fcntl;

import java.util.Random;

public class Sample {
    // 使用JNA内置的O_CREAT常量,避免手动定义错误
    private static final int O_CREAT = Fcntl.O_CREAT;
    // POSIX信号量打开失败的返回值
    private static final Pointer SEM_FAILED = Pointer.NULL;

    public static void main(String[] args) throws Exception {
        // 生成合法的POSIX信号量名字:以/开头,无其他斜杠
        String semName = "/test_sem_" + new Random().nextInt();
        
        SemaphoreLibrary semLib = Native.load("c", SemaphoreLibrary.class);
        // 打开/创建信号量:O_CREAT标志,八进制0666权限,初始值0
        Pointer semaphore = semLib.sem_open(semName, O_CREAT, 0666, 0);
        
        // 必须检查信号量是否成功打开
        if (semaphore == SEM_FAILED) {
            int errno = Native.getLastError();
            throw new RuntimeException("Failed to open semaphore: errno=" + errno + " (" + Native.getErrorString(errno) + ")");
        }

        try {
            int postResult = semLib.sem_post(semaphore);
            if (postResult != 0) {
                int errno = Native.getLastError();
                throw new RuntimeException("sem_post failed: errno=" + errno + " (" + Native.getErrorString(errno) + ")");
            }
            System.out.println("sem_post executed successfully!");
        } finally {
            // 关闭信号量
            semLib.sem_close(semaphore);
            // 不再需要的话,删除信号量(避免IPC对象残留)
            semLib.sem_unlink(semName);
        }
    }

    // 修正拼写错误:Sempahore → Semaphore
    interface SemaphoreLibrary extends Library {
        Pointer sem_open(String name, int flags, int mode, int value);
        int sem_post(Pointer sem);
        int sem_close(Pointer sem);
        // 添加sem_unlink用于删除不再需要的信号量
        int sem_unlink(String name);
    }
}

额外注意事项

  • 确保你的项目依赖了JNA和JNA-Platform,比如Maven依赖:
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>5.13.0</version>
</dependency>
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna-platform</artifactId>
    <version>5.13.0</version>
</dependency>
  • Linux系统默认支持POSIX信号量,但如果是容器环境,需要确认容器有足够的IPC权限。
  • 调用sem_unlink很重要,否则创建的信号量会一直留在系统中,直到重启或者手动删除。

内容的提问来源于stack exchange,提问作者Rafael Winterhalter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:02:18