Ⅰ linux下C語言編程,跟目錄操作相關的有個DIR數據結構,是個結構體的,具體是怎麼定義的。求解惑
APUE中大致是這么說的:DIR結構是個內部結構,作用類似於FILE結構,讀目錄時我們並不版關系DIR結構的細節,它只是作為opendir的返權回值,以及readdir、rewinddir、closedir、telldir、seekdir的函數的操作對象,讀目錄是只調用這些函數就行了,就像我們使用FILE結構一樣,很少有人關注FILE的定義。另外,只有內核才能寫目錄。
Ⅱ Linux下怎麼讀取多個進程的信息
首先說說DIR這一結構體,以下為DIR結構體的定義:
struct __dirstream
{
void *__fd;
char *__data;
int __entry_data;
char *__ptr;
int __entry_ptr;
size_t __allocation;
size_t __size;
__libc_lock_define (, __lock)
};
typedef struct __dirstream DIR;
DIR結構體類似於FILE,是一個內部結構,以下幾個函數用這個內部結構保存當前正在被讀取的目錄的有關信息(摘自《UNIX環境高級編程(第二版)》)。函數 DIR *opendir(const char *pathname),即打開文件目錄,返回的就是指向DIR結構體的指針,而該指針由以下幾個函數使用:
struct dirent *readdir(DIR *dp);
void rewinddir(DIR *dp);
int closedir(DIR *dp);
long telldir(DIR *dp);
void seekdir(DIR *dp,long loc);
關於DIR結構,我們知道這么多就可以了,沒必要去再去研究他的結構成員。
接著是dirent結構體,首先我們要弄清楚目錄文件(directory file)的概念:這種文件包含了其他文件的名字以及指向與這些文件有關的信息的指針(摘自《UNIX環境高級編程(第二版)》)。從定義能夠看出,dirent不僅僅指向目錄,還指向目錄中的具體文件,readdir函數同樣也讀取目錄下的文件,這就是證據。以下為dirent結構體的定義:
struct dirent
{
long d_ino; /* inode number 索引節點號 */
off_t d_off; /* offset to this dirent 在目錄文件中的偏移 */
unsigned short d_reclen; /* length of this d_name 文件名長 */
unsigned char d_type; /* the type of d_name 文件類型 */
char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最長255字元 */
}
然後是怎麼使用它讀取進程信息。可以用這些函數來讀取/proc下的文件夾,然後做一個判斷,只要文件夾的名字開頭是1-9的,就進入目錄讀取其中的status文件,然後輸出信息。
代碼
#include <stdio.h>
#include <dirent.h>
#include <unistd.h>
#include <stdlib.h>
typedef struct{
pid_t pid;
char name[256];//進程名稱
int vmsize;//虛擬內存信息
}proc_info_st;//保存讀取的進程信息
#define PROC_NAME_LINE 1//名稱所在行
#define PROC_PID_LINE 4//pid所在行
#define PROC_VMSIZE_LINE 12//虛擬內存所在行
#define BUFF_LEN 1024 //行緩沖區的長度
#ifndef TRUE
# define TRUE 1
#endif
#ifndef FALSE
# define FALSE 0
#endif
void read_proc(proc_info_st* info,const char* c_pid);//讀取進程信息
int read_line(FILE* fp,char* buff,int b_l,int l);//讀取一行
int main()
{
//打開目錄
DIR *dir;
struct dirent *ptr;
if (!(dir = opendir("/proc")))
return 0;
//讀取目錄
while (ptr = readdir(dir))
{//循環讀取出所有的進程文件
if (ptr->d_name[0] > '0' && ptr->d_name[0] <= '9')
{
//獲取進程信息
proc_info_st info;
read_proc(&info,ptr->d_name);//讀取信息
printf("pid:%d\npname:%s\nvmsize:%d\n",info.pid,info.name,info.vmsize);
printf("\n\n");//再空兩行
}
}
}
/**************************************************
**說明:根據進程pid獲取進程信息,存放在proc_info_st結構體中
**
**輸入:
** /proc_info_st* info 返回進程信息
** /char* c_pid 進程pid的字元串形式
**
**
**
*************************************************/
void read_proc(proc_info_st* info,const char* c_pid)
{
FILE* fp = NULL;
char file[512] = {0};
char line_buff[BUFF_LEN] = {0};//讀取行的緩沖區
sprintf(file,"/proc/%s/status",c_pid);//讀取status文件
if (!(fp = fopen(file,"r")))
{
printf("read %s file fail!\n",file);
return;
}
char name[32];
//先讀取進程名稱
if (read_line(fp,line_buff,BUFF_LEN,PROC_NAME_LINE))
{
sscanf(line_buff,"%s %s",name,(info->name));
}
fseek(fp,0,SEEK_SET);//回到文件頭部
//讀取進程pid
if (read_line(fp,line_buff,BUFF_LEN,PROC_PID_LINE))
{
sscanf(line_buff,"%s %d",name,&(info->pid));
}
fseek(fp,0,SEEK_SET);//回到文件頭部
//讀取進程vmsize
if (read_line(fp,line_buff,BUFF_LEN,PROC_VMSIZE_LINE))
{
sscanf(line_buff,"%s %d",name,&(info->vmsize));
}
fclose(fp);
}
/**************************************************
**說明:讀取文件的一行到buff
**
**輸入:
** /FILE* fp 文件指針
** /char* buff 緩沖區
** /int b_l 緩沖區的長度
** /l 指定行
**
**輸出:
** /true 讀取成功
** /false 讀取失敗
*************************************************/
int read_line(FILE* fp,char* buff,int b_l,int l)
{
if (!fp)
return FALSE;
char line_buff[b_l];
int i;
//讀取指定行的前l-1行,轉到指定行
for (i = 0; i < l-1; i++)
{
if (!fgets (line_buff, sizeof(line_buff), fp))
{
return FALSE;
}
}
//讀取指定行
if (!fgets (line_buff, sizeof(line_buff), fp))
{
return FALSE;
}
memcpy(buff,line_buff,b_l);
return TRUE;
}
如果你想更深入的了解一些東西可以參考下http://www.linuxprobe.com/chapter-09.html,希望能對你有幫助