LoginSignup
5
4

More than 5 years have passed since last update.

【自分用】プロセスとかファイルディスクリプタをSwiftからlibcを使って確認してみる

Posted at

次のような書籍の勉強中なので、
その内容理解とSwiftからCを触ってみる練習のための自分用メモです。

以後、全て対話式にSwiftを動かしています。

$ swift

libcを使う(macOS)

// macOSの場合
import Darwin
// Linuxの場合
// import Glibc

PID, PPID

PID取得

let pid = getpid()
// -> pid: pid_t = 48846

別ウィンドウで取得したPIDのプロセスを確認

$ ps -p 48846

  PID TTY           TIME CMD
48846 ttys000    0:00.04 /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/repl_swift

対話式で起動しているので、repl_swiftが動いているよう

親プロセスのPID取得

let ppid = getppid()
// ppid: pid_t = 48847

同じく別ウィンドウで取得したPIDのプロセスを確認

$ ps -p 48847

  PID TTY           TIME CMD
48847 ttys000    0:00.11 /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/debugserver --native-regs --setsid --reverse-connect 127.0.0.1:59152

システムコール

man 2 getpid
# man 2 getppid も同じ

補足

PIDだけならSwiftのFoundationで可能

import Foundation
ProcessInfo().processIdentifier
// -> $R12: Int32 = 48846

getpid()の返り値はpid_t, ProcessInfo().processIdentifierの返り値はInt32

ProcessInfo().processIdentifier == getpid()
// $R16: Bool = true

比較できるので、pid_tはInt32のエイリアスなのかな?


ファイルディスクリプタ

標準入力、標準出力、標準エラー(stdin, stdout, stderr)

標準入力、標準出力、標準エラーのファイルディスクリプタはそれぞれ、 0, 1, 2 と決まっているので、それを確認する。

libcを読み込んだので、stdin, stdout, stderrが使える。

- 標準入力のファイルディスクリプタ

let stdinFileNo = fileno(stdin)
// -> stdinFileNo: Int32 = 0

- 標準出力のファイルディスクリプタ

let stdoutFileNo = fileno(stdout)
// -> stdoutFileNo: Int32 = 1

- 標準出力のファイルディスクリプタ

let stderrFileNo = fileno(stderr)
// -> stderrFileNo: Int32 = 2

ちなみに、stdin, stdout, stderrの型はUnsafeMutablePointer<FILE>

type(of: stdin)
// -> $R2: UnsafeMutablePointer<FILE>.Type = UnsafeMutablePointer<__sFILE>

また、Cライブラリでは、 STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO というマクロが用意されているとのこと。

// libcを読み込んでいるので、これもSwiftから呼べる
STDIN_FILENO
// -> $R9: Int32 = 0
STDOUT_FILENO
// -> $R10: Int32 = 1
STDERR_FILENO
// -> $R11: Int32 = 2

ファイルを開いてファイルディスクリプタの確認

let fd = open("test.txt", O_RDONLY)
// -> fd: Int32 = 5
// ファイルディスクリプタ 5 が返ってきた

let fd2 = open("test2.txt", O_RDONLY)
// -> fd2: Int32 = 6
// ファイルディスクリプタ 6 が返ってきた

close(fd)
// -> $R7: Int32 = 0
// ファイルを閉じる
// ファイルディスクリプタ 5 が再利用可能になった

let fd3 = open("test3.txt", O_RDONLY)
// -> fd: Int32 = 5
// 先ほどファイルを閉じたことで再利用可能になったファイルディスクリプタ 5 が使われた

fileno()関数は Swift Package Manager でも使ってるっぽい。

システムコール

man 2 open
man 2 close

とりあえずここまで。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4