En linux los procesos listos para la ejecución estan en un cola de espera <especial para la ejecucion>,
un determinado proceso con el estado TASK_RUNNING indica que esta ejecutandose(actualmente)o en espera
de ejecución, al terminar ésta porción de tiempo se recoje otro proceso de esa cola.

Es cierto que podemos tener un arbol de 200 procesos(o tantos como se quiera) corriendo a la vez
y paresca que todos están en TASK_RUNNING ésto no es cierto ya que el procesador utiliza esa cola para
determinar en que momento se acaba esa ejecución y empieza una nueva.


La funcion schedule() permite "liberar" al procesador para otros usos en cuanto a procesos (ésto no se limita solo
a éste ejemplo), claro que esto tiene un costo y es poner a aquéllos procesos a dormir o TASK_INTERRUPTIBLE,
solo si el proceso contiene el estado TASK_RUNNING, esto quiere decir que éstan a la espera de un evento,
ya sea de hardware o una "llamada" nuestra, que podría ser, por ejemplo los timers del kernel(tema que ya trate en posts anteriores).
Al usar una función como wake_up_process() estamos por obviedad, cambiando el estado de aquel proceso a TASK_RUNNING
"reinsertandolo" en la cola de ejecución de espera.

Existen 2 tipos de sueños:
1. INTERRUPTIBLE - el proceso puede ser despertado por señales o interrupciones del hardware y regresa a TASK_RUNNING
2. UNINTERRUPTIBLE - el proceso no puede ser despertado por el programador, si no por un evento de forma explícita.
Una señal "ininterrumpible" podrían ser aquella que se realizan en el contexto atomico(tema que ya toque también).

Entonces decidí programar ésta pequeña función como prueba de concepto, su uso es enviar una señal por medio del kernel a
tal proceso, y se configura con 3 señas FREEZE_PROCESS(congela un proceso), REFRIGERATE_PROCESS(lo refrigera si ésta congelado
aunque no funcióna en todos los casos), KILL_PROCESS(mata un proceso).
Código:
/*--------------------------------------------
 
    Autor: NvK
    Descripción: Enviar señales a un proceso para tomar control de el.Se lo puede matar, congelar o refrigerar.
    Fecha: 27-1-2014
 
----------------------------------------------*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>

#define REFRIGERATE_PROCESS 	18
#define FREEZE_PROCESS 			19
#define KILL_PROCESS 			15

static uint8_t send_signal_process(__u32 _pid,
                                    struct pid *pid_struct,
                                    struct task_struct *_ktask,
                                    __u8 _signal)
{
    atomic_t pid_status;
    pid_struct= task_pid(_ktask);
    if( ((*_ktask).pid==_pid)&&(pid_struct!=NULL) )
    {
        _ktask->state= TASK_INTERRUPTIBLE;
        schedule();
        kill_pid(pid_struct, _signal, TASK_INTERRUPTIBLE);
        atomic_set(&pid_status, SIGHUP);
    }
    else
    {
        atomic_set(&pid_status, SIGABRT);
    }
     
    return atomic_read(&pid_status);
}
#define freeze_process(_pid, pid_struct, _ktask) send_signal_process(_pid, pid_struct, kern_ts, FREEZE_PROCESS)
#define refrigerate_process(_pid, pid_struct, _ktask) send_signal_process(_pid, pid_struct, kern_ts, REFRIGERATE_PROCESS)
#define kill_process(_pid, pid_struct, _ktask) send_signal_process(_pid, pid_struct, kern_ts, KILL_PROCESS)
Ejemplo - 1
// Se necesitan definir éstas estructuras.
struct task_struct *kern_ts;
static struct pid *pid_struct;
unsigned int pid;

static int __section(.init.text) __cold notrace
 INIT_KERNEL(void)
{
  printk(KERN_INFO "[Driver OK]\n");
  
  kern_ts= &init_task;
  for(;(kern_ts=next_task(kern_ts))!=&init_task;)
  {
  	send_signal_process(1787, pid_struct, kern_ts, KILL_PROCESS); // esto matara al proceso con el PID 1787
  }

  return 0;
}
Ejemplo - 2 (lo mismo pero con macros, más facil)
for(;(kern_ts=next_task(kern_ts))!=&init_task;)
  {
  	kill_process(1968, pid_struct, kern_ts); // mata
	freeze_proces(3638, pid_struct, kern_ts); // congela
	refrigerate_process(3638, pid_struct, kern_ts); // descongela
  }
Conclusión:
Al moverse fuera de la cola de ejecución(cualquiera sea sus estados), deja de planificarse para esa ejecución
lo que por logica básica lo pone a dormir.
Bro me encanta este material. me gustaría ponerlo en practica. que necesito instalarme? con una virtual con una distribución linux(Puppy Linux,Slitaz,Xubuntu,Vector linux) que requiera poco recursos puedo?

saludos
Imagen
Muy buen trabajo el tuyo se nota que le das bien duro sigue asi y espero ver mas aportes tuyos de este tipo que son realmente interesantes y de mucho merito, un saludo crack
Abolición para el torneo del toro de la vega. Death to the murderers of bulls.
Gracias a los 2 por los comentarios..
@Pink, esto son kernel modules, y están testeadas y funcionales para backtrack 5 R2 y R3, yo los hago/pruebo en mi maquina virtual(también en una física que tengo).
Si quieres puedo hacer un tuto de como programar los suyos propios, cargarlos, etc.. todo funciona dinámicamente, saludos.
PD: Backtrack tiene un kernel monolítico.
Pues la verdad seria muy bueno e interesante. requiere mucha lectura el tema. pero es fascinante.

saludos
Imagen
Solo dame un tiempo a que lo prepare, y si la verdad es mucha lectura... lo más difícil son estudiarse las estructuras del kernel, el manejo de memoria, entender la mmu, mecanimos como los ipc, irq, funcionamiento de paginación, etc...
pero entenderás más como funcionan los procesador y el hardware en general.
Responder

Volver a “Fuentes”