Skip to content

POSIX API 使用

源:POSIX Platform Library

Kotlin/Native 预置了完整的 POSIX API 绑定,可直接调用系统底层功能。本文介绍常用 POSIX API 的使用。

文件操作

基础文件 I/O

kotlin
@OptIn(ExperimentalForeignApi::class)
import platform.posix.*

fun readFile(path: String): String? {
    val file = fopen(path, "r") ?: return null
    
    try {
        memScoped {
            val buffer = allocArray<ByteVar>(4096)
            val content = buildString {
                while (true) {
                    val line = fgets(buffer, 4096, file) ?: break
                    append(line.toKString())
                }
            }
            return content
        }
    } finally {
        fclose(file)
    }
}

fun writeFile(path: String, content: String): Boolean {
    val file = fopen(path, "w") ?: return false
    
    try {
        content.cstr.use { cStr ->
            fputs(cStr.ptr, file)
        }
        return true
    } finally {
        fclose(file)
    }
}

文件描述符操作

kotlin
@OptIn(ExperimentalForeignApi::class)
fun lowLevelFileIO() {
    // 打开文件
    val fd = open("/tmp/test.txt", O_RDWR or O_CREAT, 0x644)
    if (fd < 0) {
        perror("open failed")
        return
    }
    
    try {
        // 写入数据
        val data = "Hello, POSIX!".cstr
        write(fd, data.ptr, data.size.toULong())
        
        // 移动文件指针
        lseek(fd, 0, SEEK_SET)
        
        // 读取数据
        memScoped {
            val buffer = allocArray<ByteVar>(100)
            val bytesRead = read(fd, buffer, 100u)
            println("Read: ${buffer.toKString()}")
        }
    } finally {
        close(fd)
    }
}

进程管理

创建子进程

kotlin
@OptIn(ExperimentalForeignApi::class)
fun executeCommand(command: String): Int {
    val pid = fork()
    
    when {
        pid < 0 -> {
            // Fork 失败
            perror("fork failed")
            return -1
        }
        pid == 0 -> {
            // 子进程
            execlp("/bin/sh", "sh", "-c", command, null)
            // 如果 exec 返回,说明失败
            perror("exec failed")
            exit(1)
        }
        else -> {
            // 父进程,等待子进程
            memScoped {
                val status = alloc<IntVar>()
                waitpid(pid, status.ptr, 0)
                return WEXITSTATUS(status.value)
            }
        }
    }
    return 0
}

环境变量

kotlin
@OptIn(ExperimentalForeignApi::class)
fun environmentVariables() {
    // 获取环境变量
    val home = getenv("HOME")?.toKString()
    println("HOME: $home")
    
    // 设置环境变量
    setenv("MY_VAR", "value", 1)
    
    // 删除环境变量
    unsetenv("MY_VAR")
}

目录操作

遍历目录

kotlin
@OptIn(ExperimentalForeignApi::class)
fun listDirectory(path: String): List<String> {
    val dir = opendir(path) ?: return emptyList()
    val files = mutableListOf<String>()
    
    try {
        while (true) {
            val entry = readdir(dir) ?: break
            val name = entry.pointed.d_name.toKString()
            if (name != "." && name != "..") {
                files.add(name)
            }
        }
    } finally {
        closedir(dir)
    }
    
    return files
}

文件状态

kotlin
@OptIn(ExperimentalForeignApi::class)
fun getFileInfo(path: String) {
    memScoped {
        val statBuf = alloc<stat>()
        if (stat(path, statBuf.ptr) == 0) {
            println("Size: ${statBuf.st_size}")
            println("Mode: ${statBuf.st_mode.toString(8)}")
            println("UID: ${statBuf.st_uid}")
            println("GID: ${statBuf.st_gid}")
            
            // 检查文件类型
            when {
                S_ISREG(statBuf.st_mode.toUInt()) -> println("Regular file")
                S_ISDIR(statBuf.st_mode.toUInt()) -> println("Directory")
                S_ISLNK(statBuf.st_mode.toUInt()) -> println("Symbolic link")
            }
        }
    }
}

网络编程

Socket 基础

kotlin
@OptIn(ExperimentalForeignApi::class)
fun createTcpSocket(): Int {
    return socket(AF_INET, SOCK_STREAM, 0)
}

fun connectToServer(host: String, port: Int): Int {
    val sockfd = createTcpSocket()
    if (sockfd < 0) return -1
    
    memScoped {
        val addr = alloc<sockaddr_in>()
        addr.sin_family = AF_INET.toUShort()
        addr.sin_port = htons(port.toUShort())
        
        // 解析主机名
        inet_pton(AF_INET, host, addr.sin_addr.ptr)
        
        val result = connect(
            sockfd,
            addr.ptr.reinterpret(),
            sizeOf<sockaddr_in>().toUInt()
        )
        
        if (result < 0) {
            close(sockfd)
            return -1
        }
    }
    
    return sockfd
}

时间处理

时间戳与格式化

kotlin
@OptIn(ExperimentalForeignApi::class)
fun timeOperations() {
    // 获取当前时间戳
    val now = time(null)
    println("Unix timestamp: $now")
    
    // 转换为本地时间
    memScoped {
        val tm = localtime(cValuesOf(now))?.pointed
        tm?.let {
            println("Year: ${it.tm_year + 1900}")
            println("Month: ${it.tm_mon + 1}")
            println("Day: ${it.tm_mday}")
            println("Hour: ${it.tm_hour}")
        }
        
        // 格式化时间
        val buffer = allocArray<ByteVar>(100)
        strftime(buffer, 100u, "%Y-%m-%d %H:%M:%S", tm)
        println(buffer.toKString())
    }
}

信号处理

注册信号处理器

kotlin
@OptIn(ExperimentalForeignApi::class)
val signalHandler = staticCFunction<Int, Unit> { sig ->
    println("Received signal: $sig")
}

fun setupSignals() {
    signal(SIGINT, signalHandler)
    signal(SIGTERM, signalHandler)
}

POSIX API 提供了强大的系统级编程能力,是实现跨平台 Native 应用的基础。