"I think the major good idea in Unix was its clean
and simple interface: open, close, read, and write"
Ken Thompson
- Solaris: Buceando en el Kernel con mdb (I)
- Solaris: Navegando en el /proc (III)
- Solaris: Navegando en el /proc (II)
- Solaris: Crea tu propio comando fuser
- Solaris: Navegando en el /proc (I)
- Solaris: Analizando ficheros Core Dump
Uno de los comandos más utilizado en el día a día de la administración en Solaris es fuser, el cual acepta como parámetro el nombre de un fichero o directorio y nos devuelve el pid de todos los procesos que tienen abierto dicho fichero. Esto nos permite identificar qué procesos están utilizando un sistema de archivos que deseamos desmontar, por ejemplo o cual es el proceso que tiene abierto un fichero, el cual necesitamos borrar, todos conocemos el daño que nos puede hacer borrar un fichero de un directorio, mientras que dicho fichero está abierto por un proceso, pero este es otro tema que veremos otro día.
Existe en Solaris una llamada a sistema, la cual no se encuentra documentada ya que es considerada una llamada a sistemas privada, la cual nos permite conocer qué procesos están utilizando un fichero o directorio determinado, esta llamada es utssys() la cual, mediante un puntero nos devuelve un arrays de elementos de tipo f_user_t, este tipo de dato está definido en el fichero sys/utssys.h y consiste en una estructura con 3 campos:
fu_pid ID del proceso.
fu_flags son flags definen el uso que el proceso está haciendo del fichero.
fu_uid es el ID del usuario propietario del proceso.
El siguiente ejemplo tiene únicamente una finalidad didáctica, en él se hará uso de la utssys() y además se utilizará uno de los ficheros del procfs que mantiene información sobre el proceso para sacar el nombre del mismo. El fichero que vamos a utilizar es /proc/< PID >/psinfo.
1 #include < stdio.h >
2 #include < sys/types.h >
3 #include < sys/utssys.h >
4 #include < fcntl.h >
5
6 #define _STRUCTURED_PROC 1
7 #include < sys/procfs.h >
8
9 main(int argc,char **argv)
10 {
11 char sfile[80];
12 f_user_t *info;
13 struct psinfo pinfo;
14 int nusr,n,fd;
15 char cadena[256];
16 char cflag[20];
17
18 if (argc<2)
19 {printf("\n\tUso: %s \n\n",argv[0]);return;}
20
21 sprintf(sfile,"%s",argv[1]);
22
23 info = (f_user_t *)malloc(sizeof(f_user_t) * 256);
24 nusr = utssys(sfile, 0, UTS_FUSERS, info);
25 if (nusr <0)
26 { free(info);perror("utssys: Se ha producido un error.");}
27
28 printf("\nPID\tPROC\t\tFLAG\tFILE ");
29 printf("\n---------------------------------------------------------");
30
31 for(n=0;n< nusr;n++)
32 {
33 sprintf(cadena,"/proc/%d/psinfo",(info+n)->fu_pid);
34 fd=open(cadena,O_RDWR);
35 if (fd<0)
36 {free(info);perror("\nopen: No se puede abrir el fichero");return;}
37 if(read(fd,&pinfo,sizeof(struct psinfo))<0)
38 {free(info);perror("\nread: No se puede leer el fichero");return;}
39
40 switch((info+n)->fu_flags)
41 {
42 case F_CDIR:
43 sprintf(cflag,"Actual");
44 break;
45 case F_RDIR:
46 sprintf(cflag,"root");
47 break;
48 case F_TEXT:
49 sprintf(cflag,"Text");
50 break;
51 case F_MAP:
52 sprintf(cflag,"Mapped");
53 break;
54 case F_OPEN:
55 sprintf(cflag,"Open");
56 break;
57 }
58
59
60 printf("\n%d %d\t%s\t\t%s\t%s ",(info+n)->fu_pid,(info+n)->fu_uid,pinfo.pr_fname,cflag,sfile);
61 close(fd);
62 }
63
64 free(info);
65 printf("\n\n");
66 return;
67 }
En la línea 23 se realiza la reserva de memoria para el array de elementos de tipo f_user_t.
En la línea 24 se realiza la llamada utssys() a la cual pasamos como parámetros, el nombre del directorio y el puntero de la zona de memoria que hemos reservado, la llamada devuelve el número de elementos que se ha almacenado en la memoria reservada. Como podemos ver esta forma de llamar a la función no es demasiado refinada, ya que necesitamos reservar memoria antes de conocer cuantos elementos vamos a tener, al ser un ejemplo cuya pretensión es meramente didáctico lo dejaremos así.
En la línea 34 abrimos el fichero /proc/< PID >/psinfo.
En la 37 leemos del fichero y almacenamos la información en una estructura de tipo struct psinfo
En la 60, mediante la llamada printf presentamos todos los datos.
La salida del comando sería algo parecido a:
(root@huelva)# ./myfuser /var/adm/messages PID PROC FLAG FILE --------------------------------------------------------- 5021 syslogd Open /var/adm/messages (root@huelva)#
 
 
 
Algunos derechos reservados. Licencia Creative Commons