Java 如何使用JNA读取Linux命令的输出

Java 如何使用JNA读取Linux命令的输出,java,jna,Java,Jna,我想使用JNA在java中调用Linuxmount命令,并从调用结果中填充挂载点列表,但无法理解接口方法的实际返回类型 如果我使用int,那么它会打印-1而没有任何错误。我认为这是某种错误的迹象 public class MountTest { private interface CLibrary extends Library { String[] mount(); } public static void main(String[] args) { CLibrary IN

我想使用JNA在java中调用Linuxmount命令,并从调用结果中填充挂载点列表,但无法理解接口方法的实际返回类型

如果我使用int,那么它会打印-1而没有任何错误。我认为这是某种错误的迹象

public class MountTest {

private interface CLibrary extends Library {
    String[] mount();
}

public static void main(String[] args) {
    CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);

    System.out.println(INSTANCE.mount());
}
}

我尝试根据下面的单据使用不同的退货类型,但没有任何效果

我想我的问题是基于的签名不正确

:仔细检查导致崩溃的方法的签名,以确保所有参数的大小和类型都合适。特别注意本机指针的变化。另请参见有关调试结构定义的信息

谁能帮我一下吗。我应该使用什么返回类型才能访问装载点列表

更新: 我可以通过如下调整代码来运行Linux命令:

public class MountTest {

private interface CLibrary extends Library {
    CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
    int runCommand(String cmd);
}

public static void main(String[] args) {
    CLibrary.INSTANCE.runCommand("mount");
}
}

现在,问题是,它打印到标准输出。我不知道如何通过文档读取使用JNA的标准输出的结果

mount()附加源指定的文件系统(通常是 指向设备的路径名,但也可以是设备的路径名 目录或文件,或伪字符串)到位置(目录或 文件)由目标中的路径名指定

这意味着
mount
syscall只是挂载目录,这与。您可能正在寻找,它将列出您的所有文件系统装入点,实现如下:

public interface CLibrary extends Library {
    CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
    Pointer fopen(String name, String mode);
    Mount.ByReference getmntent(Pointer FILE);
}

public static void main(String[] args) {
    final Pointer mountFile = CLibrary.INSTANCE.fopen("/etc/mtab", "r");
    if (mountFile == null) {
        System.err.println("File not exists: " + mountFile);
        return;
    }
    Mount.ByReference mpoint;
    while ((mpoint = CLibrary.INSTANCE.getmntent(mountFile)) != null) {
        System.out.println(mpoint);
    }

}

public static class Mount extends Structure {
    public String mnt_fsname;
    public String mnt_dir;
    public String mnt_type;
    public String mnt_opts;
    public int mnt_freq;
    public int mnt_passno;

    @Override
    protected List getFieldOrder() {
        List<String> fieds = new ArrayList<>();
        for (final Field f : Mount.class.getDeclaredFields()) {
            if (!f.isSynthetic())
                fieds.add(f.getName());
        }
        return fieds;
    }

    public static class ByReference extends Mount implements Structure.ByReference {
    }
}
公共接口CLibrary扩展库{
CLibrary实例=(CLibrary)Native.loadLibrary(“c”,CLibrary.class);
指针fopen(字符串名称、字符串模式);
Mount.ByReference getmntent(指针文件);
}
公共静态void main(字符串[]args){
最终指针mountFile=CLibrary.INSTANCE.fopen(“/etc/mtab”,“r”);
if(mountFile==null){
System.err.println(“文件不存在:+mountFile”);
返回;
}
Mount.ByReference mpoint;
而((mpoint=CLibrary.INSTANCE.getmnent(mountFile))!=null){
系统输出打印项次(mpoint);
}
}
公共静态类挂载扩展结构{
公共字符串mnt_fsname;
公共字符串mnt_dir;
公共字符串mnt_类型;
公共字符串mnt_opts;
公共int mnt_freq;
公共国际通行证;
@凌驾
受保护列表getFieldOrder(){
列表字段=新的ArrayList();
for(最后一个字段f:Mount.class.getDeclaredFields()){
如果(!f.isSynthetic())
fieds.add(f.getName());
}
返回封地;
}
公共静态类ByReference扩展了Mount实现结构。ByReference{
}
}
Obs:据我所知,您不能从JNA调用编译后的程序,只能调用库函数和系统调用,因此不可能调用mount命令,如果您确实想使用此命令,那么您可能需要使用
Runtime.getRuntime().exec
或类似的东西


更新

看看这里,您可以通过文档区分什么是程序,什么是系统调用或库函数

mount()附加源指定的文件系统(通常是 指向设备的路径名,但也可以是设备的路径名 目录或文件,或伪字符串)到位置(目录或 文件)由目标中的路径名指定

这意味着
mount
syscall只是挂载目录,这与。您可能正在寻找,它将列出您的所有文件系统装入点,实现如下:

public interface CLibrary extends Library {
    CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
    Pointer fopen(String name, String mode);
    Mount.ByReference getmntent(Pointer FILE);
}

public static void main(String[] args) {
    final Pointer mountFile = CLibrary.INSTANCE.fopen("/etc/mtab", "r");
    if (mountFile == null) {
        System.err.println("File not exists: " + mountFile);
        return;
    }
    Mount.ByReference mpoint;
    while ((mpoint = CLibrary.INSTANCE.getmntent(mountFile)) != null) {
        System.out.println(mpoint);
    }

}

public static class Mount extends Structure {
    public String mnt_fsname;
    public String mnt_dir;
    public String mnt_type;
    public String mnt_opts;
    public int mnt_freq;
    public int mnt_passno;

    @Override
    protected List getFieldOrder() {
        List<String> fieds = new ArrayList<>();
        for (final Field f : Mount.class.getDeclaredFields()) {
            if (!f.isSynthetic())
                fieds.add(f.getName());
        }
        return fieds;
    }

    public static class ByReference extends Mount implements Structure.ByReference {
    }
}
公共接口CLibrary扩展库{
CLibrary实例=(CLibrary)Native.loadLibrary(“c”,CLibrary.class);
指针fopen(字符串名称、字符串模式);
Mount.ByReference getmntent(指针文件);
}
公共静态void main(字符串[]args){
最终指针mountFile=CLibrary.INSTANCE.fopen(“/etc/mtab”,“r”);
if(mountFile==null){
System.err.println(“文件不存在:+mountFile”);
返回;
}
Mount.ByReference mpoint;
而((mpoint=CLibrary.INSTANCE.getmnent(mountFile))!=null){
系统输出打印项次(mpoint);
}
}
公共静态类挂载扩展结构{
公共字符串mnt_fsname;
公共字符串mnt_dir;
公共字符串mnt_类型;
公共字符串mnt_opts;
公共int mnt_freq;
公共国际通行证;
@凌驾
受保护列表getFieldOrder(){
列表字段=新的ArrayList();
for(最后一个字段f:Mount.class.getDeclaredFields()){
如果(!f.isSynthetic())
fieds.add(f.getName());
}
返回封地;
}
公共静态类ByReference扩展了Mount实现结构。ByReference{
}
}
Obs:据我所知,您不能从JNA调用编译后的程序,只能调用库函数和系统调用,因此不可能调用mount命令,如果您确实想使用此命令,那么您可能需要使用
Runtime.getRuntime().exec
或类似的东西


更新


看看这里,您可以区分什么是程序,什么是系统调用或库函数

如何使用JNA直接调用mount函数,并查看其返回值(int)确定它是否成功:我想要的是所有当前连接的文件系统的列表,实际上是已知装载点的列表。我不认为返回值在这种情况下会有帮助。直接调用mount函数,使用JNA,并查看其返回值(int)以确定它是否成功:我想要的是所有当前连接的文件系统的列表,它实际上是已知装载点的列表。我不认为返回值在这种情况下会有帮助