gitee.com/h79/goutils@v1.22.10/common/system/process_darwin.go (about)

     1  //go:build darwin
     2  // +build darwin
     3  
     4  package system
     5  
     6  import (
     7  	"bytes"
     8  	"encoding/binary"
     9  	"syscall"
    10  	"unsafe"
    11  )
    12  
    13  type darwinProcess struct {
    14  	pid    int32
    15  	ppid   int32
    16  	binary string
    17  }
    18  
    19  func (p *darwinProcess) Pid() int32 {
    20  	return p.pid
    21  }
    22  
    23  func (p *darwinProcess) PPid() int32 {
    24  	return p.ppid
    25  }
    26  
    27  func (p *darwinProcess) Name() string {
    28  	return p.binary
    29  }
    30  
    31  func (p *darwinProcess) Path() string {
    32  	return ""
    33  }
    34  
    35  func getProcesses() ([]Process, error) {
    36  	buf, err := darwinSyscall()
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  
    41  	procs := make([]*kernInfoProc, 0, 50)
    42  	k := 0
    43  	for i := kernInfoStructSize; i < buf.Len(); i += kernInfoStructSize {
    44  		proc := &kernInfoProc{}
    45  		err = binary.Read(bytes.NewBuffer(buf.Bytes()[k:i]), binary.LittleEndian, proc)
    46  		if err != nil {
    47  			return nil, err
    48  		}
    49  		k = i
    50  		procs = append(procs, proc)
    51  	}
    52  
    53  	result := make([]Process, 0, len(procs))
    54  	for _, p := range procs {
    55  		result = append(result, &darwinProcess{
    56  			pid:    p.Pid,
    57  			ppid:   p.PPid,
    58  			binary: darwinCString(p.Comm),
    59  		})
    60  	}
    61  	return result, nil
    62  }
    63  
    64  func darwinCString(s [16]byte) string {
    65  	i := 0
    66  	for _, b := range s {
    67  		if b != 0 {
    68  			i++
    69  		} else {
    70  			break
    71  		}
    72  	}
    73  
    74  	return string(s[:i])
    75  }
    76  
    77  func darwinSyscall() (*bytes.Buffer, error) {
    78  	mib := [4]int32{ctrlKern, kernProc, kernProcAll, 0}
    79  	size := uintptr(0)
    80  
    81  	_, _, errno := syscall.Syscall6(
    82  		syscall.SYS___SYSCTL,
    83  		uintptr(unsafe.Pointer(&mib[0])),
    84  		4,
    85  		0,
    86  		uintptr(unsafe.Pointer(&size)),
    87  		0,
    88  		0)
    89  
    90  	if errno != 0 {
    91  		return nil, errno
    92  	}
    93  
    94  	bs := make([]byte, size)
    95  	_, _, errno = syscall.Syscall6(
    96  		syscall.SYS___SYSCTL,
    97  		uintptr(unsafe.Pointer(&mib[0])),
    98  		4,
    99  		uintptr(unsafe.Pointer(&bs[0])),
   100  		uintptr(unsafe.Pointer(&size)),
   101  		0,
   102  		0)
   103  
   104  	if errno != 0 {
   105  		return nil, errno
   106  	}
   107  
   108  	return bytes.NewBuffer(bs[0:size]), nil
   109  }
   110  
   111  const (
   112  	ctrlKern           = 1
   113  	kernProc           = 14
   114  	kernProcAll        = 0
   115  	kernInfoStructSize = 648
   116  )
   117  
   118  type kernInfoProc struct {
   119  	_    [40]byte
   120  	Pid  int32
   121  	_    [199]byte
   122  	Comm [16]byte
   123  	_    [301]byte
   124  	PPid int32
   125  	_    [84]byte
   126  }