Dump进程(任务)中的所有通信端口

//
// main.m
// MachPortDump
//
// Created by haidragon on 2019/6/10.
// Copyright ? 2019 haidragon. All rights reserved.
//
//
//#import <Foundation/Foundation.h>
//
//int main(int argc, const char * argv[]) {
// @autoreleasepool {
// // insert code here...
// NSLog(@"Hello, World!");
// }
// return 0;
//}
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <sys/sysctl.h>
#include <servers/bootstrap.h>
#include <mach/mach.h>
#pragma mark ***** Compatibility Note
#pragma mark ***** The Code

static const char *gProgramName;

static void PrintPortSetMembers(mach_port_t taskSendRight, mach_port_name_t portSetName)
// For a given Mach port set within a given task, print the members
// of the port set.
{
kern_return_t err;
kern_return_t junk;
mach_port_name_array_t memberNames;
mach_msg_type_number_t memberNamesCount;
mach_msg_type_number_t memberIndex;

memberNames = NULL;

// Get an array of members.

err = mach_port_get_set_status(
taskSendRight,
portSetName,
&memberNames,
&memberNamesCount
);

// Iterate over the array, printing each one. Note that we print 6 members to
// a line and we start every line except the second with enough spaces to
// account for the information that we print that‘s common to each type
// of output.

if (err == KERN_SUCCESS) {
fprintf(stdout, " ");
for (memberIndex = 0; memberIndex < memberNamesCount; memberIndex++) {
if ( (memberIndex != 0) && (memberIndex % 6) == 0) {
// 6 columns of (8 characters plus space)
// plus DNR column (3 chars) plus space
fprintf(stdout, "\n%*s ", (6 * (8 + 1)) + 3 + 1, "");
}
fprintf(stdout, "%#8x ", memberNames[memberIndex]);
}
} else {
fprintf(stdout, "??? ");
}

// Clean up.

if (memberNames != NULL) {
junk = vm_deallocate(mach_task_self(), (vm_address_t) memberNames, memberNamesCount * sizeof(*memberNames));
assert(junk == KERN_SUCCESS);
}
}

static void PrintPortReceiveStatus(mach_port_t taskSendRight, mach_port_name_t receiveRight)
// Print information about the Mach receive right in the specified
// task.
{
kern_return_t err;
mach_port_status_t status;
mach_msg_type_number_t statusCount;

// Get information about the the right.

statusCount = MACH_PORT_RECEIVE_STATUS_COUNT;
err = mach_port_get_attributes(
taskSendRight,
receiveRight,
MACH_PORT_RECEIVE_STATUS,
(mach_port_info_t) &status,
&statusCount
);
assert( (err != KERN_SUCCESS) || (statusCount == MACH_PORT_RECEIVE_STATUS_COUNT) );

// Print it, as a group of flags followed by 6 columns of numbers,
// which are basically all counters.

if (err == KERN_SUCCESS) {
fprintf(
stdout,
"%c%c%c ",
(status.mps_nsrequest ? ‘N‘ : ‘-‘),
(status.mps_pdrequest ? ‘P‘ : ‘-‘),
(status.mps_srights ? ‘S‘ : ‘-‘)
);

fprintf(
stdout,
"%8u %8u %8u %8u %8u %8u",
status.mps_seqno,
status.mps_mscount,
status.mps_qlimit,
status.mps_msgcount,
status.mps_sorights,
status.mps_pset
);
// The kernel always sets mps_flags to 0, so we don‘t both printing it.
assert(status.mps_flags == 0);
} else {
fprintf(
stdout,
"??? %8s %8s %8s %8s %8s %8s",
"???", "???", "???", "???", "???", "???"
);
}
}

static kern_return_t PrintProcessPortSpace(pid_t pid, bool verbose)
// Prints port rights owned by the specified process.
{
kern_return_t err;
kern_return_t junk;
mach_port_t taskSendRight;
mach_port_name_array_t rightNames;
mach_msg_type_number_t rightNamesCount = 0;
mach_port_type_array_t rightTypes;
mach_msg_type_number_t rightTypesCount = 0;
unsigned int i;

taskSendRight = MACH_PORT_NULL;
rightNames = NULL;
rightTypes = NULL;

// Get the task control port for the process.

err = task_for_pid(mach_task_self(), pid, &taskSendRight);
if (err != KERN_SUCCESS) {
fprintf(stderr, "%s: Could not attach to process %lld (%#08x).\n", gProgramName, (long long) pid, err);
}

// Get a snapshot of the port name space for the task.

if (err == KERN_SUCCESS) {
err = mach_port_names(taskSendRight, &rightNames, &rightNamesCount, &rightTypes, &rightTypesCount);
}
if (err == KERN_SUCCESS) {
if ( rightNamesCount != rightTypesCount ) {
fprintf(stderr, "%s: Count mismatch (%u/%u)\n", gProgramName, rightNamesCount, rightTypesCount);
err = KERN_FAILURE;
}
}

// Print that snapshot.

if (err == KERN_SUCCESS) {
fprintf(stdout, " Name Send Receive SendOnce PortSet DeadName DNR");
if (verbose) {
fprintf(stdout, " flg seqno mscount qlimit msgcount sorights pset");
}
fprintf(stdout, "\n");
fprintf(stdout, " ---- ---- ------- -------- ------- -------- ---");
if (verbose) {
fprintf(stdout, " --- ----- ------- ------ -------- -------- ----");
}
fprintf(stdout, "\n");

// For each name, print a reference count of each type of right. If running
// verbose, print other information as well.

for (i = 0; i < rightNamesCount; i++) {
mach_port_right_t right;

// We print the right name in hex because it makes it easier to
// see the index and generation fields. See <mach/port.h> for
// information about this.

fprintf(stdout, "%#8x ", rightNames[i]);

for (right = MACH_PORT_RIGHT_SEND; right <= MACH_PORT_RIGHT_DEAD_NAME; right++) {
mach_port_urefs_t refCount;

// If the rightTypes for this name has the bit associated
// with this type of right set (that is, if the name
// references this type of right), get the name‘s reference
// for this right and print it. Otherwise just print an
// empty string to keep the columns lined up.

if (rightTypes[i] & MACH_PORT_TYPE(right)) {

err = mach_port_get_refs(taskSendRight, rightNames[i], right, &refCount);
if (err == KERN_SUCCESS) {
fprintf(stdout, "%8d ", refCount);
} else {
fprintf(stdout, "%8s ", "???");
}
} else {
fprintf(stdout, "%8s ", "");
}
}
if ( rightTypes[i] & MACH_PORT_TYPE_DNREQUEST ) {
fprintf(stdout, "yes ");
} else {
fprintf(stdout, " ");
}

if (verbose) {
if (rightTypes[i] & MACH_PORT_TYPE_PORT_SET) {
PrintPortSetMembers(taskSendRight, rightNames[i]);
} else if (rightTypes[i] & MACH_PORT_TYPE_RECEIVE) {
PrintPortReceiveStatus(taskSendRight, rightNames[i]);
}
}
fprintf(stdout, "\n");
}
}

// Clean up.

if (rightNames != NULL) {
junk = vm_deallocate(mach_task_self(), (vm_address_t) rightNames, rightNamesCount * sizeof(*rightNames));
assert(junk == KERN_SUCCESS);
}
if (rightTypes != NULL) {
junk = vm_deallocate(mach_task_self(), (vm_address_t) rightTypes, rightTypesCount * sizeof(*rightTypes));
assert(junk == KERN_SUCCESS);
}
if (taskSendRight != MACH_PORT_NULL) {
junk = mach_port_deallocate(mach_task_self(), taskSendRight);
assert(junk == KERN_SUCCESS);
}

return err;
}

typedef struct kinfo_proc kinfo_proc;

static int GetBSDProcessList(kinfo_proc **procList, size_t *procCount)
// Returns a list of all BSD processes on the system. This routine
// allocates the list and puts it in *procList and a count of the
// number of entries in *procCount. You are responsible for freeing
// this list (use "free" from System framework).
// On success, the function returns 0.
// On error, the function returns a BSD errno value.
{
int err;
kinfo_proc * result;
bool done;
static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
// Declaring name as const requires us to cast it when passing it to
// sysctl because the prototype doesn‘t include the const modifier.
size_t length;

assert( procList != NULL);
assert(*procList == NULL);
assert(procCount != NULL);

*procCount = 0;

// We start by calling sysctl with result == NULL and length == 0.
// That will succeed, and set length to the appropriate length.
// We then allocate a buffer of that size and call sysctl again
// with that buffer. If that succeeds, we‘re done. If that fails
// with ENOMEM, we have to throw away our buffer and loop. Note
// that the loop causes use to call sysctl with NULL again; this
// is necessary because the ENOMEM failure case sets length to
// the amount of data returned, not the amount of data that
// could have been returned.

result = NULL;
done = false;
do {
assert(result == NULL);

// Call sysctl with a NULL buffer.

length = 0;
err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1,
NULL, &length,
NULL, 0);
if (err == -1) {
err = errno;
}

// Allocate an appropriately sized buffer based on the results
// from the previous call.

if (err == 0) {
result = malloc(length);
if (result == NULL) {
err = ENOMEM;
}
}

// Call sysctl again with the new buffer. If we get an ENOMEM
// error, toss away our buffer and start again.

if (err == 0) {
err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1,
result, &length,
NULL, 0);
if (err == -1) {
err = errno;
}
if (err == 0) {
done = true;
} else if (err == ENOMEM) {
assert(result != NULL);
free(result);
result = NULL;
err = 0;
}
}
} while (err == 0 && ! done);

// Clean up and establish post conditions.

if (err != 0 && result != NULL) {
free(result);
result = NULL;
}
*procList = result;
if (err == 0) {
*procCount = length / sizeof(kinfo_proc);
}

assert( (err == 0) == (*procList != NULL) );

return err;
}

static int FindProcessByName(const char *processName, pid_t *pid)
// Find the process that best matches processName and return
// its PID. It first tries to find an exact match; if that fails
// it tries to find a substring match; if that fails it checks
// whether processName is a number and returns that as the PID.
//
// On entry, processName must not be NULL, and it must not be the
// empty string. pid must not be NULL.
// On success, *pid will be the process ID of the found process.
// On error, *pid is undefined.
{
int err;
int foundCount;
kinfo_proc * processList;
size_t processCount;
size_t processIndex;

assert(processName != NULL);
assert(processName[0] != 0); // needed for strstr to behave
assert(pid != NULL);

processList = NULL;

foundCount = 0;

// Get the list of all processes.

err = GetBSDProcessList(&processList, &processCount);

if (err == 0) {

// Search for an exact match.

for (processIndex = 0; processIndex < processCount; processIndex++) {
if ( strcmp(processList[processIndex].kp_proc.p_comm, processName) == 0 ) {
*pid = processList[processIndex].kp_proc.p_pid;
foundCount = 1;
break;
}
}

// If that failed, search for a substring match.

if (foundCount == 0) {
for (processIndex = 0; processIndex < processCount; processIndex++) {
if ( strstr(processList[processIndex].kp_proc.p_comm, processName) != NULL ) {
*pid = processList[processIndex].kp_proc.p_pid;
foundCount += 1;
}
}
}

// If we found more than 1, that‘s ambiguous and we error out.

if (foundCount > 1) {
fprintf(stderr, "%s: ‘%s‘ does not denote a unique process.\n", gProgramName, processName);
err = EINVAL;
}
}

// If still not found, try processName as a PID.

if ( (err == 0) && (foundCount == 0) ) {
char * firstInvalid;

*pid = (pid_t) strtol(processName, &firstInvalid, 10);
if ( (processName[0] == 0) || (*firstInvalid != 0) ) {
err = EINVAL;
}
}

free(processList);

return err;
}

static void PrintUsage(void)
{
fprintf(stderr, "usage: %s [options] [ [ pid | name ]... ]\n", gProgramName);
fprintf(stderr, " Send, Receive, SendOnce, PortSet, DeadName = right reference counts\n");
fprintf(stderr, " DNR = dead name request\n");
fprintf(stderr, " -w wide output, with lots of extra info\n");
fprintf(stderr, " flg = N (no senders) P (port dead) S (send rights)\n");
fprintf(stderr, " seqno = sequence number\n");
fprintf(stderr, " mscount = make-send count\n");
fprintf(stderr, " qlimit = queue limit\n");
fprintf(stderr, " msgcount = message count\n");
fprintf(stderr, " sorights = send-once right count\n");
fprintf(stderr, " pset = port set count\n");
}

int main(int argc, char * argv[])
{
kern_return_t err = 0;
bool verbose;
int ch;
int argIndex;

// Set gProgramName to the last path component of argv[0]

gProgramName = strrchr(argv[0], ‘/‘);
if (gProgramName == NULL) {
gProgramName = argv[0];
} else {
gProgramName += 1;
}

// Parse our options.

verbose = false;
do {
ch = getopt(argc, argv, "w");
if (ch != -1) {
switch (ch) {
case ‘w‘:
verbose = true;
break;
case ‘?‘:
default:
PrintUsage();
exit(EXIT_FAILURE);
break;
}
}
} while (ch != -1);

// Handle the remaining arguments. If none, we work against ourselves.
// Otherwise each string is treated as a process name, and we look that
// up using FindProcessByName.

if (argv[optind] == NULL) {
err = PrintProcessPortSpace(getpid(), verbose);
} else {
for (argIndex = optind; argIndex < argc; argIndex++) {
pid_t pid = 0;

if (argIndex > optind) {
fprintf(stdout, "\n");
}
if (argv[argIndex][0] == 0) {
err = EINVAL;
} else {
err = FindProcessByName(argv[argIndex], &pid);
}
if (err == 0) {
fprintf(stdout, "Mach ports for ‘%s‘ (%lld):\n", argv[argIndex], (long long) pid);
fprintf(stdout, "\n");

err = PrintProcessPortSpace(pid, verbose);
}

if (err != 0) {
break;
}
}
}

if (err != 0) {
fprintf(stderr, "%s: Failed with error %d.\n", gProgramName, err);
}
return (err == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}


原文地址:https://blog.51cto.com/haidragon/2407067

时间: 2024-10-10 05:00:25

Dump进程(任务)中的所有通信端口的相关文章

Nginx 中 fastcgi_pass 监听端口 unix socket和tcp socket差

Nginx 中 fastcgi_pass 监听端口 unix socket和tcp socket差别 Nginx连接fastcgi的方式有2种:unix domain socket和TCP,Unix domain socket 或者 IPC socket是一种终端,可以使同一台操作系统上的两个或多个进程进行数据通信.与管道相比,Unix domain sockets 既可以使用字节流和数据队列,而管道通信则只能通过字节流.Unix domain sockets的接口和Internet socke

【进程编程】——msg进程间的消息队列通信

           [进程编程]--msg进程间的消息队列通信 消息队列就像一个链表,先进先出,就像排队打饭,先到先买!键值 用来获取消息队列的描述字,我感觉就像是一个定位标识符! 函数一     key_t ftok(char *pathname,char proj)返回的是一个键值------>创建队列之前一定要获取这个键值!proj:项目名,不为零即可 打开.创建函数二     int msgget(key_t key,int msgflg) //看见没,这里是要求键值的. key:键值

C#中使用TCP通信

TCP通信需要通信双方都在线,所以需要先启动服务端进行监听,客户端才能获得连接,服务端代码: static void Main(string[] args) { TcpClient client = null; NetworkStream stream = null; byte[] buffer = null; string receiveString = null; IPAddress localIP = IPAddress.Parse("127.0.0.1"); int local

LordPe dump进程内存实现

#include <windows.h> #include <tlhelp32.h> #include <stdio.h> #include <string.h> //进程的第一个模块即为进程的 基址 (这里顺便获取进程内存映像的大小) DWORD GetProcessBaseAndImageSize(DWORD dwPID, DWORD *dwImageSize) { HANDLE hModuleSnap = INVALID_HANDLE_VALUE; M

OC中的socket通信

现在很多客户端和服务器之间的交互都是通过JSON或者XML进行的,但是有时候如果数据量较小,JSON和XML就显得比较冗余 •Socket允许使用长连接,允许应用程序运行在异步模式(提高效率),只有在需要的时候才接收数据 •在iOS中以NSStream(流)来发送和接收数据 •可以设置流的代理,对流状态的变化做出相应 –连接建立 –接收到数据 –连接关闭 – 1.NSStream:数据流的父类,用于定义抽象特性,例如:打开.关闭代理,NSStream继承自CFStream(Core Founda

C#中使用UDP通信

UDP通信是无连接通信,客户端在发送数据前无需与服务器端建立连接,即使服务器端不在线也可以发送,但是不能保证服务器端可以收到数据. 服务器端代码: C#代码   static void Main(string[] args) { UdpClient client = null; string receiveString = null; byte[] receiveData = null; //实例化一个远程端点,IP和端口可以随意指定,等调用client.Receive(ref remotePo

Android中的HTTP通信

前言:近期在慕课网学习了慕课网课程Android中的HTTP通信,就自己总结了一下,其中参考了不少博文,感谢大家的分享. 文章内容包括:1.HTTP简介2.HTTP/1.0和HTTP/1.1之间的区别3.HTTP的请求头.响应头和状态码4.Android中的HttpUrlConnection 1.Http简介Http(Hypertext transfer protocol)定义了浏览器怎么向万维网服务器发送万维网文档,以及服务器怎么将文档发送给服务器.从层次上看,http是面向应用层协议的,它是

Linux中的nc测试端口是否开放

nc测试端口是否开放 在Linux中有一个级强大的网络工具netcat,在默认情况下面都是没有安装的,现在介绍一下安装过程 其实安装很简单 一.安装使用 1.只需输入命令yum安装: [[email protected] ~]# yum install -y nc [[email protected] ~]# yum install -y nc Loaded plugins: fastestmirror, refresh-packagekit, security Setting up Insta

C#中显现串口通信SerialPort类

SerialPort类的常用属性 名 称 说 明 BaseStream 获取 SerialPort 对象的基础 Stream 对象 BaudRate 获取或设置串行波特率 BreakState 获取或设置中断信号状态 BytesToRead 获取接收缓冲区中数据的字节数 BytesToWrite 获取发送缓冲区中数据的字节数 CDHolding 获取端口的载波检测行的状态 CtsHolding 获取"可以发送"行的状态 DataBits 获取或设置每个字节的标准数据位长度 Discar