fs/procfs/: Add support for /proc, a convenient way for getting information about the currently running task.
This commit is contained in:
parent
bbad69ab61
commit
f980200ac4
@ -170,6 +170,11 @@ static const struct procfs_entry_s g_procfs_entries[] =
|
|||||||
{ "partitions", &part_procfsoperations, PROCFS_FILE_TYPE },
|
{ "partitions", &part_procfsoperations, PROCFS_FILE_TYPE },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_FS_PROCFS_EXCLUDE_PROCESS
|
||||||
|
{ "self", &proc_operations, PROCFS_DIR_TYPE },
|
||||||
|
{ "self/**", &proc_operations, PROCFS_UNKOWN_TYPE },
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(CONFIG_FS_PROCFS_EXCLUDE_UPTIME)
|
#if !defined(CONFIG_FS_PROCFS_EXCLUDE_UPTIME)
|
||||||
{ "uptime", &uptime_operations, PROCFS_FILE_TYPE },
|
{ "uptime", &uptime_operations, PROCFS_FILE_TYPE },
|
||||||
#endif
|
#endif
|
||||||
|
@ -481,7 +481,7 @@ static ssize_t proc_status(FAR struct proc_file_s *procfile,
|
|||||||
|
|
||||||
#ifdef CONFIG_SCHED_HAVE_PARENT
|
#ifdef CONFIG_SCHED_HAVE_PARENT
|
||||||
group = tcb->group;
|
group = tcb->group;
|
||||||
DEBUGASSERT(group);
|
DEBUGASSERT(group != NULL);
|
||||||
|
|
||||||
#ifdef HAVE_GROUPID
|
#ifdef HAVE_GROUPID
|
||||||
linesize = snprintf(procfile->line, STATUS_LINELEN, "%-12s%d\n", "Group:",
|
linesize = snprintf(procfile->line, STATUS_LINELEN, "%-12s%d\n", "Group:",
|
||||||
@ -818,7 +818,7 @@ static ssize_t proc_groupstatus(FAR struct proc_file_s *procfile,
|
|||||||
int i;
|
int i;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEBUGASSERT(group);
|
DEBUGASSERT(group != NULL);
|
||||||
|
|
||||||
remaining = buflen;
|
remaining = buflen;
|
||||||
totalsize = 0;
|
totalsize = 0;
|
||||||
@ -954,7 +954,7 @@ static ssize_t proc_groupfd(FAR struct proc_file_s *procfile,
|
|||||||
size_t totalsize;
|
size_t totalsize;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
DEBUGASSERT(group);
|
DEBUGASSERT(group != NULL);
|
||||||
|
|
||||||
remaining = buflen;
|
remaining = buflen;
|
||||||
totalsize = 0;
|
totalsize = 0;
|
||||||
@ -1120,7 +1120,7 @@ static ssize_t proc_groupenv(FAR struct proc_file_s *procfile,
|
|||||||
size_t copysize;
|
size_t copysize;
|
||||||
struct proc_envinfo_s info;
|
struct proc_envinfo_s info;
|
||||||
|
|
||||||
DEBUGASSERT(group);
|
DEBUGASSERT(group != NULL);
|
||||||
|
|
||||||
/* Initialize the info structure */
|
/* Initialize the info structure */
|
||||||
|
|
||||||
@ -1183,12 +1183,23 @@ static int proc_open(FAR struct file *filep, FAR const char *relpath,
|
|||||||
return -EACCES;
|
return -EACCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The first segment of the relative path should be a task/thread ID */
|
/* The first segment of the relative path should be a task/thread ID or
|
||||||
|
* the string "self".
|
||||||
|
*/
|
||||||
|
|
||||||
ptr = NULL;
|
ptr = NULL;
|
||||||
tmp = strtoul(relpath, &ptr, 10);
|
|
||||||
|
|
||||||
if (!ptr || *ptr != '/')
|
if (strncmp(relpath, "self", 4) == 0)
|
||||||
|
{
|
||||||
|
tmp = (unsigned long)getpid(); /* Get the PID of the calling task */
|
||||||
|
ptr = (FAR char *)relpath + 4; /* Discard const */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmp = strtoul(relpath, &ptr, 10); /* Extract the PID from path */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr == NULL || *ptr != '/')
|
||||||
{
|
{
|
||||||
ferr("ERROR: Invalid path \"%s\"\n", relpath);
|
ferr("ERROR: Invalid path \"%s\"\n", relpath);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
@ -1216,7 +1227,7 @@ static int proc_open(FAR struct file *filep, FAR const char *relpath,
|
|||||||
tcb = sched_gettcb(pid);
|
tcb = sched_gettcb(pid);
|
||||||
leave_critical_section(flags);
|
leave_critical_section(flags);
|
||||||
|
|
||||||
if (!tcb)
|
if (tcb == NULL)
|
||||||
{
|
{
|
||||||
ferr("ERROR: PID %d is no longer valid\n", (int)pid);
|
ferr("ERROR: PID %d is no longer valid\n", (int)pid);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
@ -1227,7 +1238,7 @@ static int proc_open(FAR struct file *filep, FAR const char *relpath,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
node = proc_findnode(ptr);
|
node = proc_findnode(ptr);
|
||||||
if (!node)
|
if (node == NULL)
|
||||||
{
|
{
|
||||||
ferr("ERROR: Invalid path \"%s\"\n", relpath);
|
ferr("ERROR: Invalid path \"%s\"\n", relpath);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
@ -1244,7 +1255,7 @@ static int proc_open(FAR struct file *filep, FAR const char *relpath,
|
|||||||
/* Allocate a container to hold the task and node selection */
|
/* Allocate a container to hold the task and node selection */
|
||||||
|
|
||||||
procfile = (FAR struct proc_file_s *)kmm_zalloc(sizeof(struct proc_file_s));
|
procfile = (FAR struct proc_file_s *)kmm_zalloc(sizeof(struct proc_file_s));
|
||||||
if (!procfile)
|
if (procfile == NULL)
|
||||||
{
|
{
|
||||||
ferr("ERROR: Failed to allocate file container\n");
|
ferr("ERROR: Failed to allocate file container\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -1272,7 +1283,7 @@ static int proc_close(FAR struct file *filep)
|
|||||||
/* Recover our private data from the struct file instance */
|
/* Recover our private data from the struct file instance */
|
||||||
|
|
||||||
procfile = (FAR struct proc_file_s *)filep->f_priv;
|
procfile = (FAR struct proc_file_s *)filep->f_priv;
|
||||||
DEBUGASSERT(procfile);
|
DEBUGASSERT(procfile != NULL);
|
||||||
|
|
||||||
/* Release the file container structure */
|
/* Release the file container structure */
|
||||||
|
|
||||||
@ -1298,14 +1309,14 @@ static ssize_t proc_read(FAR struct file *filep, FAR char *buffer,
|
|||||||
/* Recover our private data from the struct file instance */
|
/* Recover our private data from the struct file instance */
|
||||||
|
|
||||||
procfile = (FAR struct proc_file_s *)filep->f_priv;
|
procfile = (FAR struct proc_file_s *)filep->f_priv;
|
||||||
DEBUGASSERT(procfile);
|
DEBUGASSERT(procfile != NULL);
|
||||||
|
|
||||||
/* Verify that the thread is still valid */
|
/* Verify that the thread is still valid */
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = enter_critical_section();
|
||||||
tcb = sched_gettcb(procfile->pid);
|
tcb = sched_gettcb(procfile->pid);
|
||||||
|
|
||||||
if (!tcb)
|
if (tcb == NULL)
|
||||||
{
|
{
|
||||||
ferr("ERROR: PID %d is not valid\n", (int)procfile->pid);
|
ferr("ERROR: PID %d is not valid\n", (int)procfile->pid);
|
||||||
leave_critical_section(flags);
|
leave_critical_section(flags);
|
||||||
@ -1382,12 +1393,12 @@ static int proc_dup(FAR const struct file *oldp, FAR struct file *newp)
|
|||||||
/* Recover our private data from the old struct file instance */
|
/* Recover our private data from the old struct file instance */
|
||||||
|
|
||||||
oldfile = (FAR struct proc_file_s *)oldp->f_priv;
|
oldfile = (FAR struct proc_file_s *)oldp->f_priv;
|
||||||
DEBUGASSERT(oldfile);
|
DEBUGASSERT(oldfile != NULL);
|
||||||
|
|
||||||
/* Allocate a new container to hold the task and node selection */
|
/* Allocate a new container to hold the task and node selection */
|
||||||
|
|
||||||
newfile = (FAR struct proc_file_s *)kmm_malloc(sizeof(struct proc_file_s));
|
newfile = (FAR struct proc_file_s *)kmm_malloc(sizeof(struct proc_file_s));
|
||||||
if (!newfile)
|
if (newfile == NULL)
|
||||||
{
|
{
|
||||||
ferr("ERROR: Failed to allocate file container\n");
|
ferr("ERROR: Failed to allocate file container\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -1422,20 +1433,30 @@ static int proc_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
|
|||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
|
finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
|
||||||
DEBUGASSERT(relpath && dir && !dir->u.procfs);
|
DEBUGASSERT(relpath != NULL && dir != NULL && dir->u.procfs == NULL);
|
||||||
|
|
||||||
/* The relative must be either:
|
/* The relative must be either:
|
||||||
*
|
*
|
||||||
* (1) "<pid>" - The sub-directory of task/thread attributes, or
|
* (1) "<pid>" - The sub-directory of task/thread attributes,
|
||||||
* (2) The name of a directory node under <pid>
|
* (2) "self" - Which refers to the PID of the calling task, or
|
||||||
|
* (3) The name of a directory node under either of those
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Otherwise, the relative path should be a valid task/thread ID */
|
/* Otherwise, the relative path should be a valid task/thread ID */
|
||||||
|
|
||||||
ptr = NULL;
|
ptr = NULL;
|
||||||
tmp = strtoul(relpath, &ptr, 10);
|
|
||||||
|
|
||||||
if (!ptr || (*ptr != '\0' && *ptr != '/'))
|
if (strncmp(relpath, "self", 4) == 0)
|
||||||
|
{
|
||||||
|
tmp = (unsigned long)getpid(); /* Get the PID of the calling task */
|
||||||
|
ptr = (FAR char *)relpath + 4; /* Discard const */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmp = strtoul(relpath, &ptr, 10); /* Extract the PID from path */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr == NULL || (*ptr != '\0' && *ptr != '/'))
|
||||||
{
|
{
|
||||||
/* strtoul failed or there is something in the path after the pid */
|
/* strtoul failed or there is something in the path after the pid */
|
||||||
|
|
||||||
@ -1461,7 +1482,7 @@ static int proc_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
|
|||||||
tcb = sched_gettcb(pid);
|
tcb = sched_gettcb(pid);
|
||||||
leave_critical_section(flags);
|
leave_critical_section(flags);
|
||||||
|
|
||||||
if (!tcb)
|
if (tcb == NULL)
|
||||||
{
|
{
|
||||||
ferr("ERROR: PID %d is not valid\n", (int)pid);
|
ferr("ERROR: PID %d is not valid\n", (int)pid);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
@ -1473,7 +1494,7 @@ static int proc_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
procdir = (FAR struct proc_dir_s *)kmm_zalloc(sizeof(struct proc_dir_s));
|
procdir = (FAR struct proc_dir_s *)kmm_zalloc(sizeof(struct proc_dir_s));
|
||||||
if (!procdir)
|
if (procdir == NULL)
|
||||||
{
|
{
|
||||||
ferr("ERROR: Failed to allocate the directory structure\n");
|
ferr("ERROR: Failed to allocate the directory structure\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -1489,7 +1510,7 @@ static int proc_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
|
|||||||
|
|
||||||
ptr++;
|
ptr++;
|
||||||
node = proc_findnode(ptr);
|
node = proc_findnode(ptr);
|
||||||
if (!node)
|
if (node == NULL)
|
||||||
{
|
{
|
||||||
ferr("ERROR: Invalid path \"%s\"\n", relpath);
|
ferr("ERROR: Invalid path \"%s\"\n", relpath);
|
||||||
kmm_free(procdir);
|
kmm_free(procdir);
|
||||||
@ -1536,7 +1557,7 @@ static int proc_closedir(FAR struct fs_dirent_s *dir)
|
|||||||
{
|
{
|
||||||
FAR struct proc_dir_s *priv;
|
FAR struct proc_dir_s *priv;
|
||||||
|
|
||||||
DEBUGASSERT(dir && dir->u.procfs);
|
DEBUGASSERT(dir != NULL && dir->u.procfs != NULL);
|
||||||
priv = dir->u.procfs;
|
priv = dir->u.procfs;
|
||||||
|
|
||||||
if (priv)
|
if (priv)
|
||||||
@ -1565,7 +1586,7 @@ static int proc_readdir(struct fs_dirent_s *dir)
|
|||||||
pid_t pid;
|
pid_t pid;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
DEBUGASSERT(dir && dir->u.procfs);
|
DEBUGASSERT(dir != NULL && dir->u.procfs != NULL);
|
||||||
procdir = dir->u.procfs;
|
procdir = dir->u.procfs;
|
||||||
|
|
||||||
/* Have we reached the end of the directory */
|
/* Have we reached the end of the directory */
|
||||||
@ -1593,7 +1614,7 @@ static int proc_readdir(struct fs_dirent_s *dir)
|
|||||||
tcb = sched_gettcb(pid);
|
tcb = sched_gettcb(pid);
|
||||||
leave_critical_section(flags);
|
leave_critical_section(flags);
|
||||||
|
|
||||||
if (!tcb)
|
if (tcb == NULL)
|
||||||
{
|
{
|
||||||
ferr("ERROR: PID %d is no longer valid\n", (int)pid);
|
ferr("ERROR: PID %d is no longer valid\n", (int)pid);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
@ -1645,7 +1666,7 @@ static int proc_rewinddir(struct fs_dirent_s *dir)
|
|||||||
{
|
{
|
||||||
FAR struct proc_dir_s *priv;
|
FAR struct proc_dir_s *priv;
|
||||||
|
|
||||||
DEBUGASSERT(dir && dir->u.procfs);
|
DEBUGASSERT(dir != NULL && dir->u.procfs != NULL);
|
||||||
priv = dir->u.procfs;
|
priv = dir->u.procfs;
|
||||||
|
|
||||||
priv->base.index = 0;
|
priv->base.index = 0;
|
||||||
@ -1677,9 +1698,18 @@ static int proc_stat(const char *relpath, struct stat *buf)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
ptr = NULL;
|
ptr = NULL;
|
||||||
tmp = strtoul(relpath, &ptr, 10);
|
|
||||||
|
|
||||||
if (!ptr)
|
if (strncmp(relpath, "self", 4) == 0)
|
||||||
|
{
|
||||||
|
tmp = (unsigned long)getpid(); /* Get the PID of the calling task */
|
||||||
|
ptr = (FAR char *)relpath + 4; /* Discard const */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmp = strtoul(relpath, &ptr, 10); /* Extract the PID from path */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr == NULL)
|
||||||
{
|
{
|
||||||
ferr("ERROR: Invalid path \"%s\"\n", relpath);
|
ferr("ERROR: Invalid path \"%s\"\n", relpath);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
@ -1703,7 +1733,7 @@ static int proc_stat(const char *relpath, struct stat *buf)
|
|||||||
tcb = sched_gettcb(pid);
|
tcb = sched_gettcb(pid);
|
||||||
leave_critical_section(flags);
|
leave_critical_section(flags);
|
||||||
|
|
||||||
if (!tcb)
|
if (tcb == NULL)
|
||||||
{
|
{
|
||||||
ferr("ERROR: PID %d is no longer valid\n", (int)pid);
|
ferr("ERROR: PID %d is no longer valid\n", (int)pid);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
@ -1741,7 +1771,7 @@ static int proc_stat(const char *relpath, struct stat *buf)
|
|||||||
/* Lookup the well-known node associated with the relative path. */
|
/* Lookup the well-known node associated with the relative path. */
|
||||||
|
|
||||||
node = proc_findnode(ptr);
|
node = proc_findnode(ptr);
|
||||||
if (!node)
|
if (node == NULL)
|
||||||
{
|
{
|
||||||
ferr("ERROR: Invalid path \"%s\"\n", relpath);
|
ferr("ERROR: Invalid path \"%s\"\n", relpath);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
Loading…
Reference in New Issue
Block a user