Slide 1

Slide 1 text

go code generation
 from C r_rudi / एࢁ ࢙࿠

Slide 2

Slide 2 text

Who are you? • @r_rudi / WAKAYAMA Shirou • CTO of Tsukinowa inc. • ansible / MQTT / Sphinx ! • No.6 of Go GitHub developers in Japan

Slide 3

Slide 3 text

psutil • A cross-platform process and system utilities module for Python • Linux/Windows/OSX/FreeBSD/Solaris • 32bit/64bit • CPU, Mem, Disk, Network, Process and so on

Slide 4

Slide 4 text

gopsutil • go port of the psutil • github.com/shirou/gopsutil • Linux/Windows/OSX/FreeBSD • 32bit/64bit • “Pure Golang"

Slide 5

Slide 5 text

How to get system information • Linux has proc filesystem • read under “/proc” • /proc/stat • /proc/mem • /proc/10/stat Thanks it’s Text

Slide 6

Slide 6 text

FreeBSD/OSX • Some of values can get from sysctl as Text ! • Some is Not Text • kern.devstat.all retunes “C struct devinfo_dev” • can not use cgo to stay “Pure golang” • (Linux /var/run/utmp is also not text) % sysctl vm.stats.vm.v_page_count vm.stats.vm.v_page_count: 1012332

Slide 7

Slide 7 text

Use syscall.Syscall • call syscall of low-level operating system primitives directory Notice:
 http://golang.org/pkg shows only Linux. 
 you must read src directory to read other platform

Slide 8

Slide 8 text

How to use syscall // freebsd MIB
 mib := []int32{CTLKern, KernDevstat, KernDevstatAll}
 
 // invoke syscall
 _, _, err = syscall.Syscall6( syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), uintptr(miblen), uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&length)), 0, 0) 
 // parse bytes to Devstat
 var ds Devstat br := bytes.NewReader(buf) Read(br, binary.LittleEndian, &ds)

Slide 9

Slide 9 text

struct Devstat from C to Go type Devstat struct { Sequence0 uint32 Allocated int32 Start_count uint32 End_count uint32 Busy_from Bintime Dev_links _Ctype_struct___0 Device_number uint32 Device_name [16]int8 Unit_number int32 Bytes [4]uint64 Operations [4]uint64 Duration [4]Bintime Busy_time Bintime Creation_time Bintime Block_size uint32 Pad_cgo_0 [4]byte Tag_types [3]uint64 Flags uint32 Device_type uint32 Priority uint32 Pad_cgo_1 [4]byte Id *byte Sequence1 uint32 Pad_cgo_2 [4]byte } struct devstat { /* Internal house-keeping fields */ u_int sequence0; /* Update sequence# */ int allocated; /* Allocated entry */ u_int start_count; /* started ops */ u_int end_count; /* completed ops */ struct bintime busy_from; /* */ STAILQ_ENTRY(devstat) dev_links; u_int32_t device_number; /* * Devstat device * number. */ char device_name[DEVSTAT_NAME_LEN]; int unit_number; u_int64_t bytes[DEVSTAT_N_TRANS_FLAGS]; u_int64_t operations[DEVSTAT_N_TRANS_FLAGS]; struct bintime duration[DEVSTAT_N_TRANS_FLAGS]; struct bintime busy_time; struct bintime creation_time; /* * Time the device was * created. */ u_int32_t block_size; /* Block size, bytes */ u_int64_t tag_types[3]; /* * The number of * simple, ordered, * and head of queue * tags sent. write by your self? Oh no no no!

Slide 10

Slide 10 text

Use “cgo -godefs" // +build ignore package disk ! /* #include #include #include */ import "C" ! type Devstat C.struct_devstat % go tool cgo -godefs types_freebsd.go > disk_freebsd_amd64.go types_freebsd.go Once you created definition, can use on other hosts.

Slide 11

Slide 11 text

godefs • godef refer other struct if defined type Devstat C.struct_devstat
 type Bintime C.struct_bintime struct devstat {
 struct bintime busy_time; };
 struct bintime { time_t sec; uint64_t frac; }; + type Devstat struct { Busy_time Bintime
 }
 type Bintime struct { Sec int64 Frac uint64 }

Slide 12

Slide 12 text

limitation • union • C's union types are represented as a Go byte array with the same length • output perfect may not perfect • some hand editing should be required…

Slide 13

Slide 13 text

Ok, how about Windows? • No need to use C struct ! ! ! ! ! • easy, huh? Modkernel32 = syscall.NewLazyDLL("kernel32.dll")
 procGetDiskFreeSpaceExW = Modkernel32.NewProc("GetDiskFreeSpaceExW")
 
 lpFreeBytesAvailable := int64(0) lpTotalNumberOfBytes := int64(0) lpTotalNumberOfFreeBytes := int64(0) 
 ret, _, err := procGetDiskFreeSpaceExW.Call(
 uintptr(unsafe.Pointer(
 syscall.StringToUTF16Ptr(path))), uintptr(unsafe.Pointer(&lpFreeBytesAvailable)), uintptr(unsafe.Pointer(&lpTotalNumberOfBytes)), uintptr(unsafe.Pointer(&lpTotalNumberOfFreeBytes)))

Slide 14

Slide 14 text

Conclusion • gopsutil can get system information • Linux/Windows/OSX/FreeBSD • use syscall.Syscall to do low-level • use “cgo -godefs” to generate Go from C