Por esto le pido a los ripers que tengan consideración y respeto por el esfuerzo
y que si van a tomar este código por lo menos den creditos...
Aca les dejo el código del driver completo más la GUI, también quería aclarar algunos conceptos
y explicaciones.
El mecanismo que use es parte de los IPC, los netlink funcionan con identificador, y son parecidos
a los sockets solamente que en lugar de bindear un puerto bindean un proceso(y no es todo ya que el mecanismo
que usan en muy complejo para explicarlo en un solo post), este queda a la escucha
de transimision de datos, y por medio de cabezeras especiales que probe el kernel es posible establecer
un arribo de datos.
Ademas los netlink fueron creados especialmente para este tipo de tarea, y sin contar que son asincrónicos
y muy optimos...
el primer código es el del driver principal(modo kernel):
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/netlink.h>
#include <net/sock.h>
#include <net/net_namespace.h>
/* si quires debuggear descomenta esta de lo contrario comentala */
#define DEBUG_ANTIFREEZE_DRIVER
/* Necesaria para interactuar con el espacio de usuario y kernel */
#define NETLINK_KERNEL_GROUP 30
#define REFRIGERATE_PROCESS 18
#define FREEZE_PROCESS 19
#define KILL_PROCESS 15
#define _KILL_PROCESS "[KILL_SIGNAL]"
#define _FREEZE_PROCESS "[FREEZE_SIGNAL]"
#define _REFRIGERATE_PROCESS "[REFRIGERATE_SIGNAL]"
#define PID_EX "[PID_EX]"
#define EZOMBIE "EXIT_ZOMBIE|"
#define EDEAD "EXIT_DEAD|"
#define TDEAD "TASK_DEAD|"
#define TKILL "TASK_KILLABLE|"
#define TTRACED "TASK_TRACED|"
#define TSTOP "TASK_STOPPED|"
#define TWAKEKILL "TASK_WAKEKILL|"
#define TWAKING "TASK_WAKING|"
#define TINTRPT "TASK_INTERRUPTIBLE|"
#define TUNINTERPT "TASK_UNINTERRUPTIBLE|"
#define TRUNN "TASK_RUNNING|"
#define TMAX "TASK_STATE_MAX|"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("NvK");
MODULE_DESCRIPTION("Modulo para controlar y obtener el consumo de procesos, pudiendolos optimizar y evitar posibles latencias");
static struct sock *nl_sk= NULL;
static struct task_struct *ktask;
static struct mm_struct *MMU;
static struct vm_area_struct *VMA;
static struct pid *pid_struct;
struct nlmsghdr *nlh= NULL;
struct sk_buff *sk_ob;
/* con un ushort basta y sobra (congela/descongela/mata un proceso en modo ring0) */
static uint8_t frozen_process_r0(__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;
kill_pid(pid_struct, _signal, TASK_INTERRUPTIBLE); //kill_pid(pid_struct, SIGSTOP, TASK_INTERRUPTIBLE);
atomic_set(&pid_status, SIGHUP);
}else
{
atomic_set(&pid_status, SIGABRT);
}
return atomic_read(&pid_status);
}
static uint8_t __attribute__((__section__(".text.init") ))
nl_KernelSend(char *Message, int nl_pid)
{
/* Necesario para enviar un mensaje */
sk_ob= nlmsg_new(strlen(Message), 0);
nlh= nlmsg_put(sk_ob, 0, 0, NLMSG_DONE, strlen(Message), 0); // escribo la estructura
NETLINK_CB(sk_ob).dst_group= 0;
strncpy(NLMSG_DATA(nlh), Message , strlen(Message));
nlmsg_unicast(nl_sk, sk_ob, nl_pid);
return 1;
}
/* Convierto la cadena de texto en integro */
static int32_t __attribute__((__section__(".text.init") ))
strcpysignal(char nl_buf[], char *type_signal)
{
int base_int;
char signal[1040];
strncpy(signal, nl_buf+strlen(type_signal), strlen(nl_buf)-1);
return simple_strtol((const char *)signal, NULL, base_int);
}
// sysctl -w vm.drop_caches=3
static void __attribute__((__section__(".text.init") ))
netlink_recv(struct sk_buff *skb)
{
int pid, pid_signal, type_signal;
char *sbuff;
char nl_buf[1024];
unsigned long get_mm, hiwater_vm,
total_vm, hiwater_rss, total_rss,
swap, size_kb;
if (skb!=NULL)
{
// Reservo el tamaño de una pagina de memoria
sbuff= (char *)vmalloc(sizeof(char)*PAGE_SIZE + 1);
memset(sbuff, 0x0000, sizeof(sbuff));
memset(nl_buf, 0x0000, sizeof(nl_buf));
nlh= (struct nlmsghdr *)skb->data;
sprintf(nl_buf, "%s", (char *)NLMSG_DATA(nlh));
#ifdef DEBUG_ANTIFREEZE_DRIVER
printk(KERN_INFO "<SEÑAL> %s\n", nl_buf);
#endif
pid_signal= -1;
if (strstr(nl_buf, _KILL_PROCESS)!=NULL)
{
pid_signal= strcpysignal(nl_buf, _KILL_PROCESS);
#ifdef DEBUG_ANTIFREEZE_DRIVER
printk(KERN_INFO "\n<PID_SIGNAL> %d (KILL_PROCESS)\n", pid_signal);
#endif
type_signal= KILL_PROCESS;
}
if (strstr(nl_buf, _FREEZE_PROCESS)!=NULL)
{
pid_signal= strcpysignal(nl_buf, _FREEZE_PROCESS);
#ifdef DEBUG_ANTIFREEZE_DRIVER
printk(KERN_INFO "\n<PID_SIGNAL> %d (FREEZE_PROCESS)\n", pid_signal);
#endif
type_signal= FREEZE_PROCESS;
}
if (strstr(nl_buf, _REFRIGERATE_PROCESS)!=NULL)
{
pid_signal= strcpysignal(nl_buf, _REFRIGERATE_PROCESS);
#ifdef DEBUG_ANTIFREEZE_DRIVER
printk(KERN_INFO "\n<PID_SIGNAL> %d (REFRIGERATE_PROCESS)\n", pid_signal);
#endif
type_signal= REFRIGERATE_PROCESS;
}
pid= nlh->nlmsg_pid;
printk(KERN_INFO "----------------------------------------------");
for(ktask= &init_task; (ktask= next_task(ktask))!=&init_task;)
{
memset(sbuff, 0x0000, sizeof(sbuff));
if (pid_signal!=-1)
frozen_process_r0((int)pid_signal, pid_struct, ktask, type_signal);
sprintf(sbuff, "(PAR)%s|",(char *)ktask->parent->comm); //(*pktask).utime
sprintf(sbuff+strlen(sbuff), "(PID)%d|", (int *)ktask->pid);
/*
if (strstr(nl_buf, "[PID_EX]")!=NULL){
if(ktask->pid==simple_strtol((const char *)strstr(nl_buf,PID_EX)+strlen(PID_EX), NULL, type_signal)){
printk("PID_EX RECIBIDO [%s]", strstr(nl_buf, PID_EX)+strlen(PID_EX));
sprintf(sbuff+strlen(sbuff), "[PID_EX]__%d__|", (int *)ktask->pid);
}
}*/
MMU= ktask->mm;
if (MMU!=0x0)
{
hiwater_vm = total_vm = MMU->total_vm;
if (hiwater_vm < MMU->hiwater_vm)
hiwater_vm = MMU->hiwater_vm;
hiwater_rss = total_rss = atomic_long_read(&MMU->rss_stat.count[MM_FILEPAGES]) + atomic_long_read(&MMU->rss_stat.count[MM_ANONPAGES]);
if (hiwater_rss < MMU->hiwater_rss)
hiwater_rss = MMU->hiwater_rss;
swap= atomic_long_read(&MMU->rss_stat.count[MM_SWAPENTS]);
sprintf(sbuff+strlen(sbuff), "(VIRT)%lu|", (unsigned long *)(MMU->total_vm<<(PAGE_SHIFT-0x0A)));
sprintf(sbuff+strlen(sbuff), "(RSS)%lu|", (unsigned long *)(total_rss << (PAGE_SHIFT - 0xA)));
sprintf(sbuff+strlen(sbuff), "(ShrVM)%lu|", (unsigned long *)(MMU->shared_vm));
sprintf(sbuff+strlen(sbuff), "(VMPeak)%lu|", (unsigned long *)(MMU->hiwater_vm<<(PAGE_SHIFT-0x0A)));
sprintf(sbuff+strlen(sbuff), "(VMHWM)%lu|", (unsigned long *)(MMU->hiwater_rss<<(PAGE_SHIFT-0x0A)));
sprintf(sbuff+strlen(sbuff), "(VmPTE)%lu|", (unsigned long *)(((PTRS_PER_PTE*sizeof(pte_t)*MMU->nr_ptes) >> 0xA)) );
sprintf(sbuff+strlen(sbuff), "(VData)%lu|", (unsigned long *)((MMU->total_vm - MMU->shared_vm - MMU->stack_vm)<<(PAGE_SHIFT-0x0A)) );
sprintf(sbuff+strlen(sbuff), "(VStack)%lu|", (unsigned long *)(MMU->stack_vm<<(PAGE_SHIFT-0x0A)) );
sprintf(sbuff+strlen(sbuff), "(VmSwap)%lu|", (unsigned long *)(swap << (PAGE_SHIFT - 0xa)) );
sprintf(sbuff+strlen(sbuff), "(VmPin)%lu|", (unsigned long *)(MMU->pinned_vm << (PAGE_SHIFT-0xA)));
sprintf(sbuff+strlen(sbuff), "(VmLib)%lu|", (unsigned long *)( ((MMU->exec_vm << (PAGE_SHIFT-0xA)) - (PAGE_ALIGN(MMU->end_code) - (MMU->start_code & PAGE_MASK)) >> 0xA)) );
VMA= MMU->mmap;
if (VMA!=0x0){
size_kb= (VMA->vm_end - VMA->vm_start)>>0x0A;
sprintf(sbuff+strlen(sbuff), "(Sz)%lu|", (unsigned long *)size_kb);
}
}
switch((*ktask).state) {
case EXIT_ZOMBIE: sprintf(sbuff+strlen(sbuff), "(FLAG)%s", EZOMBIE); break;
case EXIT_DEAD: sprintf(sbuff+strlen(sbuff), "(FLAG)%s", EDEAD); break;
case TASK_DEAD: sprintf(sbuff+strlen(sbuff), "(FLAG)%s", TDEAD); break;
case TASK_KILLABLE: sprintf(sbuff+strlen(sbuff), "(FLAG)%s", TKILL); break;
case TASK_STOPPED: sprintf(sbuff+strlen(sbuff), "(FLAG)%s", TSTOP); break;
case TASK_WAKEKILL: sprintf(sbuff+strlen(sbuff), "(FLAG)%s", TWAKEKILL); break;
case TASK_WAKING: sprintf(sbuff+strlen(sbuff), "(FLAG)%s", TWAKING); break;
case TASK_INTERRUPTIBLE: sprintf(sbuff+strlen(sbuff), "(FLAG)%s", TINTRPT); break;
case TASK_UNINTERRUPTIBLE: sprintf(sbuff+strlen(sbuff), "(FLAG)%s", TUNINTERPT); break;
case TASK_RUNNING: sprintf(sbuff+strlen(sbuff), "(FLAG)%s", TRUNN); break;
case TASK_STATE_MAX : sprintf(sbuff+strlen(sbuff), "(FLAG)%s", TMAX); break;
case TASK_TRACED : sprintf(sbuff+strlen(sbuff), "(FLAG)%s", TTRACED); break;
}
if (ktask->prio>=0 && ktask->prio<=99)
sprintf(sbuff+strlen(sbuff), "(PRIO)REALTIME|");
if (ktask->prio>=100)
sprintf(sbuff+strlen(sbuff), "(PRIO)NORMAL|");
//printk(KERN_INFO "priority: %d ", (int *)ktask->prio);
//printk(KERN_INFO "policy: %lu ", (unsigned long *)ktask->policy);
if (ktask->policy==0)
sprintf(sbuff+strlen(sbuff), "(PLY)SCHED_OTHER|");
if (ktask->policy==1)
sprintf(sbuff+strlen(sbuff), "(PLY)SCHED_FIFO|");
if (ktask->policy==2)
sprintf(sbuff+strlen(sbuff), "(PLY)SCHED_RR|");
sprintf(sbuff+strlen(sbuff), "(UT)%lu|", (unsigned long *)ktask->utime);
sprintf(sbuff+strlen(sbuff), "(ST)%lu|", (unsigned long *)ktask->stime);
sprintf(sbuff+strlen(sbuff), "(BT)%i64|", ktask->real_start_time);
nl_KernelSend(sbuff, pid);
}
nl_KernelSend("KERN_TC", pid);
if(sbuff) vfree(sbuff);
}
}
static int __section(.init.text) __cold notrace
__INIT_KERNEL(void)
{
printk(KERN_ALERT "Driver inicializado correctamente (esperando señal).");
nl_sk= netlink_kernel_create((struct net *)&(init_net),
NETLINK_KERNEL_GROUP,
0,
netlink_recv,
NULL,
THIS_MODULE);
return 0;
}
static void __section(.exit.data)
__EXIT_KERNEL(void)
{
//free_task((struct task_struct *)ktask);
sock_release(nl_sk->sk_socket);
}
module_init(__INIT_KERNEL);
module_exit(__EXIT_KERNEL);
el segundo es el driver del espacio de usuario, este el .h:
#ifndef NETLINK_USER_DRIVER_H
#define NETLINK_USER_DRIVER_H
__u8 init_netlink_driver(int NETLINK_PAYLOAD_LENGTH);
void nl_kernelSignal(char *sock_ib);
void nl_kernelStatus(char *sock_ob);
inline void release_nl_sock();
void getComm(int pid, char ob[]);
void kern_syscall();
#endif
y este el .c
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/socket.h>
#include <asm/types.h>
#include <linux/netlink.h>
#include <pthread.h>
#include "netlink_user_driver.h"
#define NETLINK_KERNEL_GROUP 30
#define INIT_NETLINK_ADDR(addr, __pid) \
memset(&addr, 0, sizeof(addr)); \
addr.nl_family= AF_NETLINK; \
addr.nl_pad= 0x0000; \
addr.nl_pid= __pid;
#define CONFIGURE_NLHDR(nlh, __pid, PAYLOAD_LENGTH) \
memset(nlh, 0, PAYLOAD_LENGTH); \
nlh->nlmsg_len= PAYLOAD_LENGTH; \
nlh->nlmsg_pid= __pid; \
nlh->nlmsg_flags= 0x0001; \
nlh->nlmsg_type= 0x0000;
#define NETLINK_MSG_HDR(_msghdr, _dest_nladdr, _iov) \
memset(&_msghdr, 0, sizeof(_msghdr)); \
_msghdr.msg_name= (void *) &_dest_nladdr; \
_msghdr.msg_namelen= sizeof(_dest_nladdr); \
_msghdr.msg_iov= &_iov; \
_msghdr.msg_iovlen= 0x0001;
// compilar con gcc -c netlink_user_driver.c
struct sockaddr_nl src_nladdr, dest_nladdr, recv_nladdr; // estructura para NETLINK Socket
struct iovec iov, iov2;
struct nlmsghdr *nlh= NULL, *nlh2= NULL;
struct msghdr msg, msg2;
static int fd;
__u8 init_netlink_driver(NETLINK_PAYLOAD_LENGTH){
fd= socket(AF_NETLINK, SOCK_RAW, NETLINK_KERNEL_GROUP);
INIT_NETLINK_ADDR(src_nladdr, getpid());
bind(fd, (struct sockaddr *)&src_nladdr, sizeof(src_nladdr)); // bindeo el proceso
INIT_NETLINK_ADDR(dest_nladdr, 0x0); // 0 por que va destinado al kernel
INIT_NETLINK_ADDR(recv_nladdr, 0x0);
nlh= (struct nlmsghdr *)malloc(NETLINK_PAYLOAD_LENGTH);
nlh2= (struct nlmsghdr *)malloc(NETLINK_PAYLOAD_LENGTH);
CONFIGURE_NLHDR(nlh, getpid(), NETLINK_PAYLOAD_LENGTH); //strncpy(NLMSG_DATA(nlh), "ACK", strlen("ACK"));
CONFIGURE_NLHDR(nlh2, getpid(), NETLINK_PAYLOAD_LENGTH);
iov.iov_base= (void *)nlh;
iov.iov_len= nlh->nlmsg_len;
iov2.iov_base= (void *)nlh2;
iov2.iov_len= nlh2->nlmsg_len;
NETLINK_MSG_HDR(msg, dest_nladdr, iov);
NETLINK_MSG_HDR(msg2, recv_nladdr, iov2);
return 1;
}
void nl_kernelSignal(char *sock_ib)
{
sprintf(NLMSG_DATA(nlh), "%s", sock_ib);
sendmsg(fd, &msg, 0x000);
}
void nl_kernelStatus(char *sock_ob)
{
recvmsg(fd, &msg2, 0x0000);
sprintf(sock_ob, "%s", (char *)NLMSG_DATA(nlh2));
}
inline void release_nl_sock(){ close(fd); }
void getComm(int pid, char ob[])
{
int f;
char buf_pid[1024] , status[2048];
memset(status, 0, sizeof(status));
memset(buf_pid, 0, sizeof(buf_pid));
sprintf(buf_pid, "/proc/%d/cmdline", pid);
f = open(buf_pid, O_RDONLY);
read(f, status, sizeof(status));
if (strcmp("", status)==0) // si status devuelve vacio
{
sprintf(buf_pid, "/proc/%d/comm", pid);
f = open(buf_pid, O_RDONLY);
read(f, status, sizeof(status));
strcpy(ob, status);
}
else
{
strcpy(ob, status);
}
printf("STATUS:%s", status);
close(f);
}
void kern_syscall(char *drv)
{
setuid(0);
system(drv);
}
y lo tercero pero no menos importante la GUI programada en pascal usando Lazarus:
unit UAntiFreezeSys;
{$mode objfpc}{$H+}
{$link netlink_user_driver.o}
{$linklib c}
interface
uses
Classes,
SysUtils,
FileUtil,
Forms,
Controls,
Graphics,
Dialogs,
StdCtrls,
ComCtrls,
Menus, ExtCtrls, Grids,
CTypes;
type
{ TAntiFreeze }
PAntiFreeze = ^TAntiFreeze;
TAntiFreeze = class(TForm)
Debug_kernel: TMemo;
Limpiar_log_debug: TButton;
Dmesg: TButton;
cbPingHighMem: TComboBox;
cbCongelar: TCheckBox;
cbMatar: TCheckBox;
cbSinAccion: TCheckBox;
combConsumoVirtual: TComboBox;
eVirtual: TLabel;
FreezeProcessRingZero: TMenuItem;
gbConsumoVirtual: TGroupBox;
killRingZero: TMenuItem;
Label1: TLabel;
FrozenQueues: TListView;
LblConsumoVirtual: TLabel;
lblMayorA: TLabel;
LvHighMemory: TListView;
LvStatus: TListView;
Delete: TMenuItem;
KillRingZeroHM: TMenuItem;
FreezeProcessRingZeroHM: TMenuItem;
RefrigerateProcessHM: TMenuItem;
pmHighMemory: TPopupMenu;
Refrigerate: TMenuItem;
RefrigerateAndKeep: TMenuItem;
PControlAntiFreeze: TPageControl;
pmStatus: TPopupMenu;
pmFrozenQueues: TPopupMenu;
RefrigerateProcess: TMenuItem;
Process: TTabSheet;
HighMemory: TTabSheet;
TabSheet1: TTabSheet;
TabSheet2: TTabSheet;
Debug: TTabSheet;
procedure cbCongelarClick(Sender: TObject);
procedure cbMatarChange(Sender: TObject);
procedure cbMatarClick(Sender: TObject);
procedure cbPingHighMemChange(Sender: TObject);
procedure cbCongelarChange(Sender: TObject);
procedure cbSinAccionChange(Sender: TObject);
procedure cbSinAccionClick(Sender: TObject);
procedure DeleteClick(Sender: TObject);
procedure DmesgClick(Sender: TObject);
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure FreezeProcessRingZeroClick(Sender: TObject);
procedure FreezeProcessRingZeroHMClick(Sender: TObject);
procedure InitDriverClick(Sender: TObject);
procedure killRingZeroClick(Sender: TObject);
procedure KillRingZeroHMClick(Sender: TObject);
procedure LblConsumoVirtualClick(Sender: TObject);
procedure Limpiar_log_debugClick(Sender: TObject);
procedure pmHighMemoryPopup(Sender: TObject);
procedure RefrigerateClick(Sender: TObject);
procedure RefrigerateAndKeepClick(Sender: TObject);
procedure PControlAntiFreezeChange(Sender: TObject);
procedure pmFrozenQueuesPopup(Sender: TObject);
procedure PMStatusPopup(Sender: TObject);
procedure RefrigerateProcessClick(Sender: TObject);
procedure RefrigerateProcessHMClick(Sender: TObject);
procedure SendKernelSignal(Message : String);
procedure SendKernelSignalHM(Message : String);
procedure SendKernelSignal_fromFQ(Message : String);
private public
Inited : Boolean;
published
property Status: TListView write LvStatus; { para uso futuro }
end;
type
PThreadAntiFreeze = ^TThreadAntiFreeze;
TThreadAntiFreeze = class(TThread)
private
protected
procedure Execute; override;
procedure AntiFreezeStartupInfo;
public
constructor Create(CreateSuspended : Boolean);
end;
function init_netlink_driver(NPL : Integer): cuint8; cdecl; external;
procedure nl_kernelSignal(sock_ib : Pchar); cdecl; external;
procedure nl_kernelStatus(sock_ob : Pchar); cdecl; external;
procedure release_nl_sock(); cdecl; external;
procedure installDriver(); cdecl; external;
procedure kern_syscall(ins : Pchar); cdecl; external;
const
NETLINK_SUCCESS = $0001;
NETLINK_PAYLOAD_LENGTH = 1024;
NETLINK_PID = '(PID)';
NETLINK_VIRTUAL_MEM = '(VIRT)';
NETLINK_RSS = '(RSS)';
NETLINK_SHR_MEM = '(ShrVM)';
NETLINK_VM_PEAK = '(VMPeak)';
NETLINK_VM_HWM = '(VMHWM)';
NETLINK_VM_PTE = '(VmPTE)';
NETLINK_VM_DATA = '(VData)';
NETLINK_VM_STACK = '(VStack)';
NETLINK_SWAP = '(VmSwap)';
NETLINK_VM_SZ = '(Sz)';
NETLINK_VM_PIN = '(VmPin)';
NETLINK_VM_LIB = '(VmLib)';
NETLINK_FLAG = '(FLAG)';
NETLINK_PARENTAL = '(PAR)';
NETLINK_PRIO = '(PRIO)';
NETLINK_POLICY = '(PLY)';
NETLINK_USER_TIME = '(UT)';
NETLINK_SYSTEM_TIME = '(ST)';
NETLINK_BOOT_TIME = '(BT)';
NETLINK_VOID = '-';
KERNEL_TASK_COMPLETED = 'KERN_TC';
KILL_PROCESS = '[KILL_SIGNAL]';
FREEZE_PROCESS = '[FREEZE_SIGNAL]';
REFRIGERATE_PROCESS = '[REFRIGERATE_SIGNAL]';
var
AntiFreeze : TAntiFreeze;
Thrd : TThreadAntiFreeze;
InitedDriver : Integer;
Buff: array [0 ..UAntiFreezeSys.NETLINK_PAYLOAD_LENGTH] of Char;
CatInfo : array [0 ..UAntiFreezeSys.NETLINK_PAYLOAD_LENGTH] of Char;
FreezeTimer : Integer = 3500;
implementation
{$R *.lfm}
(*-----------------------------------------------------
Funciones de filtrado
-------------------------------------------------------*)
procedure
AddFrozenQueue;
var
FrozenQueuesItems: TListItem;
Signal: String;
I: Integer;
begin
FrozenQueuesItems:= AntiFreeze.FrozenQueues.Items.Add;
FrozenQueuesItems.Caption:= AntiFreeze.LvStatus.Items.Item[AntiFreeze.LvStatus.Selected.Index].Caption;
Signal:= StringReplace(AntiFreeze.LvStatus.Items.Item[AntiFreeze.LvStatus.Selected.Index].SubItems.GetText, sLineBreak, '|', [rfReplaceAll, rfIgnoreCase]);
FrozenQueuesItems.SubItems.Add(COPY(Signal, 0, AnsiPos('|', Signal)-1)); // PID
{ Asigno cada valor a cada columna correspondiente y son 16 elementos los de la tabla de procesos }
for I:=0 to 16 do
begin
Delete(Signal, 1, AnsiPos('|', Signal));
if I<3 then
FrozenQueuesItems.SubItems.Add(Copy(Signal, 0, AnsiPos('|', Signal)-1)) // desde Virtual hasta Shared Mem
else if I=7 then { posicion de stack }
FrozenQueuesItems.SubItems.Add(Copy(Signal, 0, AnsiPos('|', Signal)-1))
else if I=8 then { posicion de swap }
FrozenQueuesItems.SubItems.Add(Copy(Signal, 0, AnsiPos('|', Signal)-1))
else if I>=12 then
FrozenQueuesItems.SubItems.Add(Copy(Signal, 0, AnsiPos('|', Signal)-1));
end;
end;
procedure
DeQueueFrozen;
begin
AntiFreeze.FrozenQueues.Items.Delete(AntiFreeze.FrozenQueues.Selected.Index);
end;
function
BuffToStr(InBuff : Array of Char) : string;
var I : Integer;
begin
Result:= '';
for I := 0 to sizeof(InBuff) do
Result:= Result + InBuff[I];
end;
function
sTo(buff, Src, Dst: String) : String;
begin
Result := Copy(Buff, AnsiPos(Src, Buff) + length(Src), length(Buff));
Result := Copy(Result, 0, AnsiPos(Dst, Result)-1);
end;
function
GetComm(Call:ShortString) : String;
var
FD : TextFIle;
begin
AssignFile(FD, Call);
Reset(FD);
ReadLn(FD, Result);
CloseFile(FD);
end;
procedure
__InitDriver;
var
liStatus,
liHighMem,
FrozenQueuesItems: TListItem;
Signal,
Comm,
getpid,
AddVirtMem,
AddShrMem,
AddRss,
AddStack,
AddSwap,
AddParent,
AddPid : String;
begin
try
if init_netlink_driver(NETLINK_PAYLOAD_LENGTH)=NETLINK_SUCCESS Then
begin
nl_kernelSignal(PChar('[KERN_INFO_STARTUP]'));
AntiFreeze.LvStatus.Items.Clear;
AntiFreeze.LvHighMemory.Items.Clear;
while True do
begin
{Application.ProcessMessages;}
nl_kernelStatus(Buff);
if Pos(KERNEL_TASK_COMPLETED, Buff)=1 then
Break;
getpid:= sTo(Buff, NETLINK_PID, '|');
Comm:= GetComm('/proc/'+getpid+'/cmdline');
if Length(Comm)=0 then
Comm:= GetComm('/proc/'+getpid+'/comm');
liStatus:= AntiFreeze.LvStatus.Items.Add;
liStatus.Caption:= Comm;
AddPid:= sTo(Buff, NETLINK_PID, '|');
AddShrMem:= sTo(Buff, NETLINK_SHR_MEM, '|');
with liStatus.SubItems do
begin
Add(AddPid);
if Pos(NETLINK_VIRTUAL_MEM, Buff)<>0 then
begin
AddVirtMem:= sTo(Buff, NETLINK_VIRTUAL_MEM, '|');
AddRss:= sTo(Buff, NETLINK_RSS, '|');
AddParent:= sTo(Buff, NETLINK_PARENTAL, '|');
AddStack:= sTo(Buff, NETLINK_VM_STACK, '|');
AddSwap:= sTo(Buff, NETLINK_SWAP, '|');
{ Procesos }
Add(AddVirtMem);
Add(AddRss);
Add(AddShrMem);
Add(sTo(Buff, NETLINK_VM_PEAK, '|'));
Add(sTo(Buff, NETLINK_VM_HWM, '|'));
Add(sTo(Buff, NETLINK_VM_PTE, '|'));
Add(sTo(Buff, NETLINK_VM_DATA, '|'));
Add(AddStack);
Add(AddSwap);
Add(sTo(Buff, NETLINK_VM_PIN, '|'));
Add(sTo(Buff, NETLINK_VM_LIB, '|'));
Add(sTo(Buff, NETLINK_VM_SZ, '|')+'Kb');
Add(sTo(Buff, NETLINK_FLAG, '|'));
Add(AddParent);
{ High Memory (procesos con mas alto consumo de memoria) }
if AntiFreeze.cbPingHighMem.Caption>'' then
begin
if (StrtoInt(AddVirtMem)>StrtoInt(COPY(AntiFreeze.cbPingHighMem.Caption,
0, length(AntiFreeze.cbPingHighMem.Caption)-1))) Then
begin
liHighMem := AntiFreeze.LvHighMemory.Items.Add;
liHighMem.Caption:= Comm;
liHighMem.SubItems.Add(AddPid);
liHighMem.SubItems.Add(AddVirtMem);
liHighMem.SubItems.Add(AddRss);
liHighMem.SubItems.Add(AddShrMem);
liHighMem.SubItems.Add(AddStack);
liHighMem.SubItems.Add(AddSwap);
liHighMem.SubItems.Add(sTo(Buff, NETLINK_PRIO, '|'));
liHighMem.SubItems.Add(sTo(Buff, NETLINK_POLICY, '|'));
liHighMem.SubItems.Add(sTo(Buff, NETLINK_USER_TIME, '|'));
liHighMem.SubItems.Add(sTo(Buff, NETLINK_SYSTEM_TIME, '|'));
liHighMem.SubItems.Add(sTo(Buff, NETLINK_BOOT_TIME, '|'));
liHighMem.SubItems.Add(sTo(Buff, NETLINK_FLAG, '|'));
liHighMem.SubItems.Add(AddParent);
end;
end;
if strtoInt(AddVirtMem)>strtoInt(AntiFreeze.combConsumoVirtual.Caption) then
begin
if (strtoInt(AddVirtMem)>Int64(600000))and((sTo(Buff, NETLINK_FLAG, '|')<>'TASK_STOPPED')) then
begin
if AntiFreeze.cbCongelar.Checked then
nl_kernelSignal(PChar(FREEZE_PROCESS+AddPid+'|'));
if AntiFreeze.cbMatar.Checked then
nl_kernelSignal(PChar(KILL_PROCESS+AddPid+'|'));
if NOT AntiFreeze.cbSinAccion.Checked then
begin
FrozenQueuesItems:= AntiFreeze.FrozenQueues.Items.Add;
FrozenQueuesItems.Caption:= Comm;
FrozenQueuesItems.SubItems.Add(AddPid);
FrozenQueuesItems.SubItems.Add(AddVirtMem);
FrozenQueuesItems.SubItems.Add(AddRss);
FrozenQueuesItems.SubItems.Add(AddShrMem);
FrozenQueuesItems.SubItems.Add(AddStack);
FrozenQueuesItems.SubItems.Add(AddSwap);
FrozenQueuesItems.SubItems.Add('TASK_STOPPED');
FrozenQueuesItems.SubItems.Add(AddParent);
end;
end;
end;
end
else
begin
Add(NETLINK_VOID);
Add(NETLINK_VOID);
Add(NETLINK_VOID);
Add(NETLINK_VOID);
Add(NETLINK_VOID);
Add(NETLINK_VOID);
Add(NETLINK_VOID);
Add(NETLINK_VOID);
Add(NETLINK_VOID);
Add(NETLINK_VOID);
Add(NETLINK_VOID);
Add(NETLINK_VOID);
Add(NETLINK_VOID);
Add(NETLINK_VOID);
end;
end;
FillChar(Buff, sizeof(Buff), 0);
end;
end;
finally
release_nl_sock();
end;
end;
(*-----------------------------------------------------
Thread loop para interactuar con el kernel
-------------------------------------------------------*)
constructor
TThreadAntiFreeze.Create(CreateSuspended : Boolean);
begin
FreeOnTerminate := True;
inherited Create(CreateSuspended);
end;
procedure
TThreadAntiFreeze.Execute;
begin
Synchronize(@AntiFreezeStartupInfo);
end;
procedure
TThreadAntiFreeze.AntiFreezeStartupInfo;
begin
AntiFreeze.Inited:= True;
while AntiFreeze.Inited do
begin
Application.ProcessMessages;
INC(FreezeTimer);
AntiFreeze.Label1.Caption:= 'PING '+InttoStr(FreezeTimer)+'ms';
if FreezeTimer>=3500 Then
begin
__InitDriver;
{$ASMMODE intel}
asm
XOR EAX, EAX
MOV &FreezeTimer, EAX
end;
end;
end;
end;
(*-----------------------------------------------------
TAntiFreeze
-------------------------------------------------------*)
procedure
TAntiFreeze.SendKernelSignal(Message : String);
begin
init_netlink_driver(NETLINK_PAYLOAD_LENGTH);
nl_kernelSignal(Pchar(Message+LvStatus.Selected.SubItems.GetText+'|'));
release_nl_sock();
end;
procedure
TAntiFreeze.SendKernelSignalHM(Message : String);
begin
init_netlink_driver(NETLINK_PAYLOAD_LENGTH);
nl_kernelSignal(Pchar(Message+LvHighMemory.Selected.SubItems.GetText+'|'));
release_nl_sock();
end;
procedure
TAntiFreeze.SendKernelSignal_fromFQ(Message : String);
begin
init_netlink_driver(NETLINK_PAYLOAD_LENGTH);
nl_kernelSignal(Pchar(Message+FrozenQueues.Selected.SubItems.GetText+'|'));
release_nl_sock();
end;
procedure
TAntiFreeze.InitDriverClick(Sender: TObject);
begin
LvStatus.Items.Clear;
end;
procedure
TAntiFreeze.killRingZeroClick(Sender: TObject);
begin
SendKernelSignal(KILL_PROCESS);
FreezeTimer:= 4000;
end;
procedure TAntiFreeze.KillRingZeroHMClick(Sender: TObject);
begin
SendKernelSignalHM(KILL_PROCESS);
FreezeTimer:= 4000;
end;
procedure
TAntiFreeze.FreezeProcessRingZeroClick(Sender: TObject);
begin
SendKernelSignal(FREEZE_PROCESS);
AddFrozenQueue;
FreezeTimer:= 4000;
end;
procedure TAntiFreeze.FreezeProcessRingZeroHMClick(Sender: TObject);
begin
SendKernelSignalHM(FREEZE_PROCESS);
FreezeTimer:= 4000;
end;
procedure
TAntiFreeze.RefrigerateClick(Sender: TObject);
begin
SendKernelSignal_FromFQ(REFRIGERATE_PROCESS);
DeQueueFrozen;
end;
procedure TAntiFreeze.RefrigerateProcessHMClick(Sender: TObject);
begin
SendKernelSignalHM(REFRIGERATE_PROCESS);
FreezeTimer:= 4000;
end;
procedure
TAntiFreeze.RefrigerateAndKeepClick(Sender: TObject);
begin
SendKernelSignal_FromFQ(REFRIGERATE_PROCESS);
end;
procedure TAntiFreeze.LblConsumoVirtualClick(Sender: TObject);
begin
end;
procedure TAntiFreeze.Limpiar_log_debugClick(Sender: TObject);
begin
Debug_kernel.Lines.Clear;
end;
procedure TAntiFreeze.pmHighMemoryPopup(Sender: TObject);
var
HighMemItem : TListItem;
begin
HighMemItem := LvHighMemory.Selected;
if HighMemItem = nil then
Abort;
end;
procedure
TAntiFreeze.PControlAntiFreezeChange(Sender: TObject);
begin
end;
procedure TAntiFreeze.pmFrozenQueuesPopup(Sender: TObject);
var
FrozenItem : TListItem;
begin
FrozenItem := FrozenQueues.Selected;
if FrozenItem = nil then
Abort;
end;
procedure
TAntiFreeze.pmStatusPopup(Sender: TObject);
var
Item : TListItem;
begin
Item := LvStatus.Selected;
if Item = nil then
Abort;
end;
procedure TAntiFreeze.RefrigerateProcessClick(Sender: TObject);
begin
SendKernelSignal(REFRIGERATE_PROCESS);
end;
procedure
TAntiFreeze.FormCreate(Sender: TObject);
begin
cbPingHighMem.AddItem('10000+', Sender);
cbPingHighMem.AddItem('15000+', Sender);
cbPingHighMem.AddItem('25000+', Sender);
cbPingHighMem.AddItem('35000+', Sender);
cbPingHighMem.AddItem('45000+', Sender);
cbPingHighMem.AddItem('60000+', Sender);
cbPingHighMem.AddItem('80000+', Sender);
with combConsumoVirtual do
begin
AddItem('800000', Sender);
AddItem('1000000', Sender);
AddItem('1400000', Sender);
AddItem('1800000', Sender);
AddItem('2500000', Sender);
AddItem('3000000', Sender);
AddItem('3500000', Sender);
end;
kern_syscall('/sbin/insmod nl_driver.ko');
Thrd:= TThreadAntiFreeze.Create(True);
Thrd.Priority:= tpNormal;
Thrd.Resume;
end;
procedure TAntiFreeze.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
if Inited then
begin
Thrd.Terminate;
Inited := False;
end;
kern_syscall('/sbin/rmmod nl_driver.ko');
CloseAction:= CaFree;
end;
procedure
TAntiFreeze.cbPingHighMemChange(Sender: TObject);
begin
end;
procedure TAntiFreeze.cbMatarChange(Sender: TObject);
begin
end;
procedure TAntiFreeze.cbCongelarClick(Sender: TObject);
begin
if cbCongelar.Checked Then
begin
cbMatar.Checked:= False;
cbSinAccion.Checked:= False;
end;
end;
procedure TAntiFreeze.cbMatarClick(Sender: TObject);
begin
if cbMatar.Checked then
begin
cbCongelar.Checked := False;
cbSinAccion.Checked:= False;
end;
end;
procedure TAntiFreeze.cbCongelarChange(Sender: TObject);
begin
end;
procedure TAntiFreeze.cbSinAccionChange(Sender: TObject);
begin
end;
procedure TAntiFreeze.cbSinAccionClick(Sender: TObject);
begin
if cbSinAccion.Checked Then
begin
cbCongelar.Checked:= False;
cbMatar.Checked:= False;
end;
end;
procedure
TAntiFreeze.DeleteClick(Sender: TObject);
begin
DeQueueFrozen;
end;
procedure TAntiFreeze.DmesgClick(Sender: TObject);
var
DBG_FILE : TEXTFILE;
Log: String;
begin
AssignFile(DBG_FILE, '/var/log/dmesg');
Reset(DBG_FILE);
Debug_kernel.Lines.Add('------------------------------------------------[Debug info]-----------------------------------------------');
while not eof(DBG_FILE) do
begin
ReadLn(DBG_FILE, Log);
Debug_kernel.Lines.Add(' '+Log);
end;
CloseFile(DBG_FILE);
Debug_kernel.Lines.Add('-----------------------------------------------------------------------------------------------');
end;
end.
Para compilar el driver .ko se usa make no el gcc
obj-m += nl_driver.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clear
y los parametros para compilar con gcc el driver de usuario:
gcc -c netlink_user_driver.c
Saludos NvK.