Category Archives: Linux Kernel

Programar Encendido de PC

Hace un par de días publicaban en Linux.com un artículo que me gustó mucho, consistía en usar el RTC (Real Time Clock) de la placa base para programar el encendido del PC a través del pseudo-sistema de fichero /sys.

La idea se basa en escribir en uno de los pseudo ficheros la hora a la que se desea encender la máquina. No se necesita nada más.

Uno de los beneficios que no ofrece en nuestro día a día sería poder programar un apagado por algún mantenimiento que nosotros no controlamos (podrían cortar la luz para alguna reparación) y programar un encendido cuando estimemos que se ha terminado ese mantenimiento.

Para empezar debemos comprobar que nuestra versión de Kernel soporta rtc lo vemos así:

# grep -i rtc /boot/config-$(uname -r)

Que debe devolver:

[...]
CONFIG_HPET_EMULATE_RTC=y 
CONFIG_PM_TRACE_RTC=y 
CONFIG_RTC_LIB=y 
CONFIG_RTC_CLASS=y 
CONFIG_RTC_HCTOSYS=y 
CONFIG_RTC_HCTOSYS_DEVICE="rtc0" 
[...]

También es posible verlo a través de los logs del Kernel:

# grep -i rtc /var/log/messages 
# grep -i rtc /var/log/kern.log

Que debe salir:

Dec  2 08:14:38 asgard kernel: [    0.853916] rtc_cmos 00:03: RTC can wake from S4
Dec  2 08:14:38 asgard kernel: [    0.854031] rtc_cmos 00:03: rtc core: registered rtc_cmos as rtc0
Dec  2 08:14:38 asgard kernel: [    0.854053] rtc0: alarms up to one month, y3k, 114 bytes nvram, hpet irqs
Dec  2 08:14:38 asgard kernel: [    0.855641] rtc_cmos 00:03: setting system clock to 2012-12-02 07:14:23 UTC (1354432463)

Aquí muestra un par de cosas interesantes, la primera es que el reloj está sincronizado UTC e implica que no debemos tener en cuenta el cambio de horario de verano/invierno y que el dispositivo es rtc0, podría pasar, aunque es poco frecuente, que hubiera más de uno.

Probando

Ahora ya estamos listos para probar el invento, para ello solo necesitamos dos pasos:

Primero poner a cero el contador de la alarma:

# echo 0 > /sys/class/rtc/rtc0/wakealarm

Y segundo poner la alarma:

# echo $(date '+%s' -d '+ 3 minutes') > /sys/class/rtc/rtc0/wakealarm

Si ahora hacemos un cat del fichero veremos un número como este 1354444166 que es la fecha en formato epoch (segundos transcurridos desde el 1 de enero de 1970) y es el formato de tiempo que usa UNIX internamente.

Ahora podemos apagar el PC y ver como pasados los tres minutos arranca de nuevo.

A partir de aquí ya podemos escribir un script que simplifique la tarea, si queremos que se apague a cierta hora y se encienda de nuevo sin que tengamos que preocuparnos. O cosas así.

Referencia

Artículo original publicado por Carla Schroder en Linux.com con licencia Creative Commons 3.0

Planificador

El kernel de Linux administra cuatro colas de planificación de procesos:

  • SCHED_RR: Basada en Round Robin, es una cola que asigna tiempo de procesador a los procesos de forma cíclica un tiempo finito que llamamos cuanto (q, quantum);
  • SCHED_FIFO: Basada en First In First Out, también dispone de un cuanto, pero normalmente no se usa porque no se fuerza al proceso a abandonar la CPU. Se usa en sistemas de tiempo real.
  • SCHED_OTHER: Planificación clásica de Linux. Se basa en prioridades dinámicas del sistema, que se establecen en una combinación de la prioridad de usuario y la de sistema.
  •  SCHED_YIELD : No es una política de planificación, sino un modificador que afecta a las tres políticas anteriores. El proceso cede la CPU a cualquier otro que esté listo. Se activa con una llamada al sistema (sched_yield()) sólo para el siguiente ciclo de planificación.

Para ver cómo funciona, podemos crear un programa en C que trabaje contra el planificador:

  1. Para establecer y recoger los parámetros de planificación:
     int sched_setparam(pid_t pid, const struct sched_param *p);
    int sched_getparam(pid_t pid, struct sched_param *p);
  2. Para conocer el intervalo del cuanto:
    int sched_rr_get_interval(pid_t pid, struct timespec *tp);
  3. Para conocer los algoritmos de planificación:
     int sched_setscheduler(pid_t pid, int policy, const struct sched_param *p);
    int sched_getscheduler(pid_t pid);
  4. Para conocer la el rango de prioridades estáticas:
    int sched_get_priority_max(int politica);
    int sched_get_priority_min(int politica);

Y como más vale una imagen, el código aquí