proc_pid.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. */
  9. #define __RT_IPC_SOURCE__
  10. #include "proc.h"
  11. #include "procfs.h"
  12. #include <rthw.h>
  13. #include <rtdbg.h>
  14. #include <fcntl.h>
  15. #include <errno.h>
  16. #include "lwp_internal.h"
  17. #include <dfs_dentry.h>
  18. #include "lwp_internal.h"
  19. #if defined(RT_USING_SMART)
  20. #include "lwp.h"
  21. #include "lwp_pid.h"
  22. #include <lwp_user_mm.h>
  23. struct pid_dentry
  24. {
  25. const char *name;
  26. mode_t mode;
  27. const struct dfs_file_ops *fops;
  28. const struct proc_ops *ops;
  29. const struct dfs_seq_ops *seq_ops;
  30. int (*single_show)(struct dfs_seq_file *seq, void *data);
  31. void *data;
  32. };
  33. static char stat_transform(int __stat)
  34. {
  35. switch (__stat)
  36. {
  37. case RT_THREAD_RUNNING:
  38. return 'R';
  39. default:
  40. return 'T';
  41. }
  42. }
  43. static int stat_single_show(struct dfs_seq_file *seq, void *data)
  44. {
  45. struct proc_dentry *dentry = (struct proc_dentry *)seq->file->vnode->data;
  46. rt_list_t *list;
  47. int mask = 0;
  48. rt_thread_t thread;
  49. rt_uint64_t user_time_lwp = 0;
  50. rt_uint64_t system_time_lwp = 0;
  51. int lwp_oncpu = RT_CPUS_NR;
  52. int lwp_oncpu_ok = 0;
  53. struct rt_lwp *lwp = RT_NULL;
  54. char** argv = RT_NULL;
  55. char *filename = RT_NULL;
  56. char *dot = RT_NULL;
  57. lwp_pid_lock_take();
  58. lwp = lwp_from_pid_locked(dentry->pid);
  59. argv = lwp_get_command_line_args(lwp);
  60. if (lwp)
  61. {
  62. dfs_seq_printf(seq,"%d ",dentry->pid);
  63. if (argv)
  64. {
  65. filename = strrchr(argv[0], '/');
  66. dot = strchr(argv[0], '.');
  67. if (filename != NULL)
  68. {
  69. filename++;
  70. }
  71. else
  72. {
  73. filename = argv[0];
  74. }
  75. if (dot != NULL)
  76. {
  77. *dot = '\0';
  78. }
  79. if (filename != NULL)
  80. {
  81. dfs_seq_printf(seq,"(%s) ", filename);
  82. }
  83. else
  84. {
  85. dfs_seq_printf(seq,"(%s) ", argv[0]);
  86. }
  87. lwp_free_command_line_args(argv);
  88. }
  89. else
  90. {
  91. dfs_seq_printf(seq,"(%s) ", "");
  92. }
  93. if (lwp->terminated)
  94. {
  95. dfs_seq_printf(seq,"%c ",'Z');
  96. }
  97. else
  98. {
  99. list = lwp->t_grp.next;
  100. while (list != &lwp->t_grp)
  101. {
  102. thread = rt_list_entry(list, struct rt_thread, sibling);
  103. user_time_lwp = user_time_lwp + thread->user_time;
  104. system_time_lwp = system_time_lwp + thread->system_time;
  105. #if RT_CPUS_NR > 1
  106. #define ONCPU(thread) RT_SCHED_CTX(thread).oncpu
  107. #else
  108. #define ONCPU(thread) 0
  109. #endif
  110. if (lwp_oncpu_ok == 0)
  111. {
  112. lwp_oncpu = ONCPU(thread);
  113. lwp_oncpu_ok = 1;
  114. }
  115. if (stat_transform(RT_SCHED_CTX(thread).stat) == 'R')
  116. {
  117. lwp_oncpu = ONCPU(thread);
  118. mask = 1;
  119. }
  120. list = list->next;
  121. }
  122. if (mask == 1)
  123. {
  124. dfs_seq_printf(seq,"%c ",'R');
  125. }
  126. else
  127. {
  128. dfs_seq_printf(seq,"%c ",'S');
  129. }
  130. }
  131. lwp_pid_lock_release();
  132. if (lwp->parent != NULL)
  133. dfs_seq_printf(seq,"%d ",lwp->parent->pid);
  134. else
  135. dfs_seq_printf(seq,"0 ");
  136. dfs_seq_printf(seq, "1 1 0 -1 4194560 48245 133976064 732 425574 ");
  137. dfs_seq_printf(seq,"%llu ",user_time_lwp);//utime
  138. dfs_seq_printf(seq,"%llu ",system_time_lwp);//stime
  139. dfs_seq_printf(seq, "1204291 518742 20 0 1 0 50 ");
  140. dfs_seq_printf(seq, "%d ",rt_aspace_count_vsz(lwp->aspace));//VSZ
  141. dfs_seq_printf(seq, "1422 18446744073709551615 ");
  142. dfs_seq_printf(seq, "1 1 0 0 0 0 671173123 4096 1260 0 0 0 17 ");
  143. dfs_seq_printf(seq, "%d ", lwp_oncpu);//CPU
  144. dfs_seq_printf(seq, "0 0 0 0 0 0 0 0 0 0 0 0 0");
  145. dfs_seq_printf(seq,"\n");
  146. }
  147. else
  148. {
  149. lwp_pid_lock_release();
  150. }
  151. return 0;
  152. }
  153. static int cmdline_single_show(struct dfs_seq_file *seq, void *data)
  154. {
  155. struct proc_dentry *dentry = (struct proc_dentry *)seq->file->vnode->data;
  156. struct rt_lwp *lwp;
  157. char** argv;
  158. lwp_pid_lock_take();
  159. lwp = lwp_from_pid_locked(dentry->pid);
  160. argv = lwp_get_command_line_args(lwp);
  161. lwp_pid_lock_release();
  162. if (argv)
  163. {
  164. for (int i = 0; argv[i] != NULL; i++)
  165. {
  166. dfs_seq_printf(seq, "%s ", argv[i]);
  167. }
  168. dfs_seq_puts(seq, "\n");
  169. lwp_free_command_line_args(argv);
  170. }
  171. else
  172. {
  173. dfs_seq_puts(seq, "error\n");
  174. }
  175. return 0;
  176. }
  177. struct proc_dentry *proc_pid_fd_lookup(struct proc_dentry *parent, const char *name)
  178. {
  179. struct proc_dentry *dentry = RT_NULL;
  180. char num[DIRENT_NAME_MAX];
  181. struct rt_lwp *lwp;
  182. struct dfs_fdtable *table;
  183. lwp_pid_lock_take();
  184. lwp = lwp_from_pid_locked(parent->pid);
  185. table = lwp ? &lwp->fdt : RT_NULL;
  186. lwp_pid_lock_release();
  187. if (!table)
  188. {
  189. return RT_NULL;
  190. }
  191. dfs_file_lock();
  192. for (int i = 0; i < table->maxfd; i++)
  193. {
  194. struct dfs_file *file = table->fds[i];
  195. if (file)
  196. {
  197. rt_snprintf(num, DIRENT_NAME_MAX, "%d", i);
  198. if (rt_strcmp(num, name) == 0)
  199. {
  200. dentry = rt_calloc(1, sizeof(struct proc_dentry));
  201. if (dentry)
  202. {
  203. dentry->mode = (S_IFLNK | (S_IRUSR | S_IRGRP | S_IROTH) | (S_IWUSR | S_IWGRP | S_IWOTH) | (S_IXUSR | S_IXGRP | S_IXOTH));
  204. dentry->ref_count = 1;
  205. dentry->name = rt_strdup(name);
  206. dentry->data = (void *)dfs_dentry_full_path(file->dentry);
  207. if (dentry->data == RT_NULL)
  208. {
  209. //todo add vnode->data
  210. if (file->vnode->type == FT_SOCKET)
  211. dentry->data = (void *)rt_strdup("socket");
  212. else if (file->vnode->type == FT_USER)
  213. dentry->data = (void *)rt_strdup("user");
  214. else if (file->vnode->type == FT_DEVICE)
  215. dentry->data = (void *)rt_strdup("device");
  216. else
  217. dentry->data = (void *)rt_strdup("unknown");
  218. }
  219. dentry->pid = parent->pid;
  220. break;
  221. }
  222. }
  223. }
  224. }
  225. dfs_file_unlock();
  226. return dentry;
  227. }
  228. int proc_pid_fd_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count)
  229. {
  230. int ret = 0, index = 0;
  231. struct proc_dentry *entry = (struct proc_dentry *)file->vnode->data;
  232. struct rt_lwp *lwp;
  233. struct dfs_fdtable *table;
  234. lwp_pid_lock_take();
  235. lwp = lwp_from_pid_locked(entry->pid);
  236. LWP_LOCK(lwp);
  237. table = lwp ? &lwp->fdt : RT_NULL;
  238. if (!table->fds)
  239. {
  240. LWP_UNLOCK(lwp);
  241. lwp_pid_lock_release();
  242. return 0;
  243. }
  244. count = (count / sizeof(struct dirent));
  245. if (count == 0)
  246. {
  247. LWP_UNLOCK(lwp);
  248. lwp_pid_lock_release();
  249. return -EINVAL;
  250. }
  251. dfs_file_lock();
  252. for (int i = 0; i < table->maxfd; i++)
  253. {
  254. struct dfs_file *df = table->fds[i];
  255. if (df)
  256. {
  257. if (index >= file->fpos)
  258. {
  259. struct dirent *d = dirp + index - file->fpos;
  260. d->d_type = DT_SYMLINK;
  261. d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
  262. rt_snprintf(d->d_name, DIRENT_NAME_MAX, "%d", i);
  263. d->d_namlen = rt_strlen(d->d_name);
  264. ret++;
  265. }
  266. index++;
  267. if (index - file->fpos >= count)
  268. {
  269. break;
  270. }
  271. }
  272. }
  273. dfs_file_unlock();
  274. LWP_UNLOCK(lwp);
  275. lwp_pid_lock_release();
  276. if (ret > 0)
  277. {
  278. file->fpos = index;
  279. ret = ret * sizeof(struct dirent);
  280. }
  281. return ret;
  282. }
  283. static const struct proc_ops proc_pid_fd_ops = {
  284. .lookup = proc_pid_fd_lookup,
  285. };
  286. static const struct dfs_file_ops proc_pid_fd_fops = {
  287. .getdents = proc_pid_fd_getdents,
  288. };
  289. int proc_pid_exe_readlink(struct proc_dentry *dentry, char *buf, int len)
  290. {
  291. struct rt_lwp *lwp;
  292. lwp = lwp_self();
  293. len = rt_snprintf(buf, len, "%s", lwp ? lwp->exe_file : "null");
  294. return len;
  295. }
  296. static const struct proc_ops proc_pid_exe_ops = {
  297. .readlink = proc_pid_exe_readlink,
  298. };
  299. int proc_pid_cwd_readlink(struct proc_dentry *dentry, char *buf, int len)
  300. {
  301. struct rt_lwp *lwp;
  302. lwp = lwp_self();
  303. len = rt_snprintf(buf, len, "%s", lwp ? lwp->working_directory : "null");
  304. return len;
  305. }
  306. static const struct proc_ops proc_pid_cwd_ops = {
  307. .readlink = proc_pid_cwd_readlink,
  308. };
  309. static struct pid_dentry pid_dentry_base[] = {
  310. {"cmdline", S_IFREG | S_IRUSR | S_IRGRP | S_IROTH, 0, 0, 0, cmdline_single_show, 0},
  311. {"cwd", S_IFLNK | S_IRUSR | S_IXUSR, 0, &proc_pid_cwd_ops, 0, 0},
  312. {"exe", S_IFLNK | S_IRUSR | S_IXUSR, 0, &proc_pid_exe_ops, 0, 0},
  313. {"fd", S_IFDIR | S_IRUSR | S_IXUSR, &proc_pid_fd_fops, &proc_pid_fd_ops, 0, 0, 0},
  314. {"mounts", S_IFLNK | S_IRUSR | S_IXUSR, 0, 0, 0, 0, "/proc/mounts"},
  315. {"stat", S_IFREG | S_IRUSR | S_IRGRP | S_IROTH, 0, 0, 0, stat_single_show, 0},
  316. };
  317. int proc_pid(int pid)
  318. {
  319. char pid_str[64] = {0};
  320. struct proc_dentry *dentry;
  321. rt_snprintf(pid_str, 64, "%d", pid);
  322. pid_str[63] = 0;
  323. dentry = proc_mkdir(pid_str, 0);
  324. if (dentry)
  325. {
  326. struct proc_dentry *ent;
  327. dentry->pid = pid;
  328. for (int j = 0; j < sizeof(pid_dentry_base) / sizeof(struct pid_dentry); j++)
  329. {
  330. if (S_ISDIR(pid_dentry_base[j].mode))
  331. {
  332. ent = proc_mkdir_data(pid_dentry_base[j].name, pid_dentry_base[j].mode, dentry,
  333. pid_dentry_base[j].fops, pid_dentry_base[j].data);
  334. }
  335. else if (S_ISLNK(pid_dentry_base[j].mode))
  336. {
  337. if (pid_dentry_base[j].data == RT_NULL)
  338. {
  339. pid_dentry_base[j].data = "NULL";
  340. }
  341. ent = proc_symlink(pid_dentry_base[j].name, dentry, pid_dentry_base[j].data);
  342. }
  343. else
  344. {
  345. ent = proc_create_data(pid_dentry_base[j].name, pid_dentry_base[j].mode, dentry,
  346. pid_dentry_base[j].fops, pid_dentry_base[j].data);
  347. }
  348. if (ent)
  349. {
  350. if (pid_dentry_base[j].ops)
  351. {
  352. ent->ops = pid_dentry_base[j].ops;
  353. }
  354. if (pid_dentry_base[j].seq_ops)
  355. {
  356. ent->seq_ops = pid_dentry_base[j].seq_ops;
  357. }
  358. if (pid_dentry_base[j].single_show)
  359. {
  360. ent->single_show = pid_dentry_base[j].single_show;
  361. }
  362. proc_release(ent);
  363. }
  364. }
  365. proc_release(dentry);
  366. }
  367. return 0;
  368. }
  369. int msh_proc_pid(int argc, char **argv)
  370. {
  371. if (argc > 1)
  372. {
  373. for (int i = 1; i <= argc - 1; i++)
  374. {
  375. proc_pid(atoi(argv[i]));
  376. }
  377. }
  378. return 0;
  379. }
  380. MSH_CMD_EXPORT_ALIAS(msh_proc_pid, proc_pid, proc pid);
  381. #endif