Category: sistemas operativos 2

sessão 2 – Criar, consultar, alterar e remover chaves do Registry.

Bibliografia de apoio:
Capítulo 3 do Livro Windows System Programming (da Bibliografia) (pags. 86-97)
MSDN:
Registry Functions: https://docs.microsoft.com/en-us/windows/win32/sysinfo/registry-functions
32-bit and 64-bit Application Data in the Registry: https://docs.microsoft.com/en-us/windows/win32/sysinfo/32-bit-and-64-bit-application-data-in-the-registry?redirectedfrom=MSDN

Criação de processo e espera até terminar:

TCHAR comando[TAM] = TEXT("notepad-exe ficheiro.txt");
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);

if (CreateProcess(NULL, comando, NULL, NULL, 0, 0, NULL, &si, &pi)
{
	_tprintf(TEXT("processo com PID: %d foi lançado"), pi.dwProcessId);
	WaitForSingleObject(pi.hProcess, INFINITE);
}

O editor do registry: registry editor (regedit)
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE (só admin, todos os programas que são instalados)

Para criar fica assim:

#include <windows.h>
#include <tchar.h>
#include <io.h>
#include <fcntl.h>
#include <stdio.h>

#define TAM 200

int _tmain(int argc, TCHAR* argv[]) {
    HKEY chave; //handle para a chave depois de ser aberta/criada
	//caminho e nome da chave é criada SOFTWARE\\SO2\\chaveLab, uso da contrabarra "\\"
    TCHAR chave_nome[TAM] = TEXT("SOFTWARE\\SO2\\chaveLab"), par_nome[TAM], par_valor[TAM];
    DWORD resultado; //com o que aconteceu com a chave

#ifdef UNICODE 
    _setmode(_fileno(stdin), _O_WTEXT);
    _setmode(_fileno(stdout), _O_WTEXT);
    _setmode(_fileno(stderr), _O_WTEXT);
#endif

	//para criar ou abrir uma chave do registry
    //RegCreateKeyEx retorna um valor se a chave foi criada/aberta com sucesso
    if(RegCreateKeyEx(
        //HKEY                        hKey,
        HKEY_CURRENT_USER,
        //nome da chave
        //LPCTSTR                     lpSubKey,
        chave_nome,
        //DWORD                       Reserved,
        0,
        //LPTSTR                      lpClass,
        NULL,
        //DWORD                       dwOptions, longevidade da chave
        REG_OPTION_NON_VOLATILE,
        //REGSAM                      samDesired,
        KEY_ALL_ACCESS,
        //const LPSECURITY_ATTRIBUTES lpSecurityAttributes, segurança da chave
        NULL,
       // PHKEY                       phkResult,
        &chave,
        //LPDWORD                     lpdwDisposition
        &resultado
    ) != ERROR_SUCCESS)
    {
        _tprintf(TEXT("chave não foi criada nem aberta! ERRO!"));
        return -1;
    }
	
    if(resultado == REG_CREATED_NEW_KEY)
    {
        _tprintf(TEXT("a chave foi criada: %s"), chave_nome);
    }else
    {
        _tprintf(TEXT("a chave foi criada: %s"), chave_nome);
    }
    RegCloseKey(chave); //importante: fechar sempre o Handle da chave 
    return 0;
}


Os atributos de uma chave são: nome, tipo, e valor

#include <windows.h>
#include <tchar.h>
#include <io.h>
#include <fcntl.h>
#include <stdio.h>

#define TAM 200

int _tmain(int argc, TCHAR* argv[]) {
    HKEY chave; //handle para a chave depois de ser aberta/criada
	//caminho e nome da chave é criada SOFTWARE\\SO2\\chaveLab, uso da contrabarra "\\"
    TCHAR chave_nome[TAM] = TEXT("SOFTWARE\\SO2\\chaveLab");
    TCHAR par_nome[TAM] = TEXT("1º atributo");
	TCHAR par_valor[TAM] = TEXT("É o novo valor");
    DWORD resultado; //com o que aconteceu com a chave

#ifdef UNICODE 
    _setmode(_fileno(stdin), _O_WTEXT);
    _setmode(_fileno(stdout), _O_WTEXT);
    _setmode(_fileno(stderr), _O_WTEXT);
#endif

	//para criar ou abrir uma chave do registry
    //RegCreateKeyEx retorna um valor se a chave foi criada/aberta com sucesso
    if(RegCreateKeyEx(
        //HKEY                        hKey,
        HKEY_CURRENT_USER,
        //nome da chave
        //LPCTSTR                     lpSubKey,
        chave_nome,
        //DWORD                       Reserved,
        0,
        //LPTSTR                      lpClass,
        NULL,
        //DWORD                       dwOptions, longevidade da chave
        REG_OPTION_NON_VOLATILE,
        //REGSAM                      samDesired,
        KEY_ALL_ACCESS,
        //const LPSECURITY_ATTRIBUTES lpSecurityAttributes, segurança da chave
        NULL,
       // PHKEY                       phkResult,
        &chave,
        //LPDWORD                     lpdwDisposition
        &resultado
    ) != ERROR_SUCCESS)
    {
        _tprintf(TEXT("chave não foi criada nem aberta! ERRO!"));
        return -1;
    }
	
    if(resultado == REG_CREATED_NEW_KEY)
    {
        _tprintf(TEXT("a chave foi criada: %s"), chave_nome);
    }else
    {
        _tprintf(TEXT("a chave foi aberta: %s"), chave_nome);
    }
    //criar oar nomeatributo = valor (1 por cada chamada da função)
    if(RegSetValueEx(
        //HKEY       hKey,
        chave,
        //LPCSTR     lpValueName,
        par_nome,
        //DWORD      Reserved,
        0,
        //DWORD      dwType, //tipo: string (REG_SZ), inteiro (REG_WORD), bloco de bytes (REG_BINARY)
        REG_SZ,
        //const BYTE * lpData, //ponteiro para void, dá para tudo como o malloc
        (const LPCBYTE /*igual c const BYTE **/) par_valor,
        //DWORD      cbData
        sizeof(TCHAR) * (_tcsclen(par_valor)+1)
        //+1 para o /0, para ler o /0 
    ) != ERROR_SUCCESS)
    {
        _tprintf(TEXT("Atributo %s não foi alterado nem criado ERRO\n"), par_nome);
    }
    //concatenar qq tipos de dados e guardar numa string
	//_strpintf_s (par_valor, TAM, TEXT("%s %d"), par_nome, tamanho);

	
	//consultar valor de um atributo
    //strcpy(par_nome, TEXT("2º atributo ")); //-> caso fosse necessário escrever a string em c depois de criada
    par_valor[0] = '\0';
	DWORD tamanho = sizeof(par_valor);
	if(RegQueryValueEx(
       // HKEY     hKey,
       chave,
       // LPCTSTR  lpValueName,
       par_nome,
        //LPDWORD  lpReserved, //é para consulta fica a NULL
        0,
        //LPDWORD  lpType,
        NULL,
        //LPBYTE   lpData,
        (LPCBYTE)par_valor,
        //LPDWORD  lpcbData
        &tamanho
    ) != ERROR_SUCCESS)
	{
        _tprintf(TEXT("Atributo %s não foi encotnrado!! ERRO\n"), par_nome);
	}else
	{
        _tprintf(TEXT("Atributo encontrado com o valor: %s e tamanho %d"), par_valor, tamanho);
	}

    DWORD valor_inteiro = 1022;
    valor_inteiro *= 2;
    _tcscpy_s(par_nome, TAM, TEXT("atributo inteiro"));
    if (RegSetValueEx(
        chave,
        par_nome,
        0,
        REG_DWORD,
        (LPCBYTE) &valor_inteiro,
        sizeof(DWORD)
    ) != ERROR_SUCCESS)
    {
        _tprintf(TEXT("Atributo %s não foi encotnrado!! ERRO\n"), par_nome);
    }

    _tcscpy_s(par_nome, TAM, TEXT("atributo binario"));

    if (RegSetValueEx(
        chave,
        par_nome,
        0,
        REG_BINARY,
        (LPCBYTE) &valor_inteiro,
        sizeof(DWORD)
    ) != ERROR_SUCCESS)
    {
        _tprintf(TEXT("Atributo %s não foi encotnrado!! ERRO\n"), par_nome);
    }
    RegCloseKey(chave); //importante: fechar sempre o Handle da chave 
    return 0;
}

Tags : , , ,

sessão 1 – Trabalhar com caracteres UNICODE na consola, Criar processos utilizando a Windows API e esperar pelo seu término.

Bibliografia de apoio:
Capítulos 2 e 6 do Livro Windows System Programming (da Bibliografia) (pgs. 34-37, 181-187, 192-195)
MSDN: Strings & Unicode e Processes

Como começar:

#include <stdio.h>

int main()
{
	printf("Até amanhã\n");
	getchar();
	return 0;
}

ou Use Unicdoe Character Set
ou Use Multi-Byte Character Set

apesar de estar em Use Unicdoe Character Set não é suficiente para escrever os caracteres especiais, vai ser necessário

#include <stdio.h>
#include <windows.h>
#include <tchar.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <io.h>

#define MAX 256

int _tmain(int argc, TCHAR* argv[]) {
	//argc -> numero de argumentos
	//argv -> argumentos
	////TCHAR vou aceitar argumentos com caracteres especiais

	TCHAR result[MAX] = TEXT("Olá! Este programa ainda não representa UNICODE\n");

#ifdef UNICODE 
	_setmode(_fileno(stdin), _O_WTEXT); //#include <fcntl.h> #include <io.h>
	_setmode(_fileno(stdout), _O_WTEXT); //#include <fcntl.h> #include <io.h>
	_setmode(_fileno(stderr), _O_WTEXT); //#include <fcntl.h> #include <io.h>
#endif


	_tprintf(TEXT("Frase:%s Tamanho:%d (caractares) %d (bytes)\n"), result, _tcslen(result), _tcslen(result) * sizeof(TCHAR));

	//mas se fossem funções que não trabalhem com caracteres não é necessário
	srand(time(NULL));
	int aleatorio = rand();

	_gettchar();

	return 0;
}
//manipulação de strings:
//char -> 1 bytes (caracteres que estão na tabela ASCII)
//a alternativa é usar o -> wchar (tem o dobro da capacidade, 2 bytes) e já permite armazenar caracteres UNICODE
//ao invés de ter duas versões do progrma, apenas uso uma versão do código
//TCHAR, não é um tipo nativo
//#include <windows.h>
//#include <tchar.h>
//e desta forma não vou ter que fazer duas versões do programa: para sistemas mais antigos e mais modernos
//_tmain -> main ou wamin
//uma string fixa, cada letra ocupa 2 bytes -> L"Olá! Este programa ainda não representa UNICODE\n"
//ou uso a macro TEXT("") ou _T("") -> "" para resolver as strings fixas
//e vou usar também o _tprintf -> printf ou wprintf
//_tcslen -> strlen
//_gettchar -> getchar()
//preparar a consola para mostrar caracteres wide:
//  _setmode(stdin, constante);
// _setmode(stdout, constante);
//calcular o tamanho real:
// _tcslen(result)*sizeof(TCHAR) // não interessa se está ou não em unicode
#include <windows.h>
#include <tchar.h>
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
#define MAX 256

//LPTSTR -> TCHAR *
//LPCTSTR -> const THACAR *


int _tmain(int argc, LPTSTR argv[]) {
	TCHAR str[MAX], result[MAX] = TEXT("Olá! Este programa é para aceitar UNICODE. Insira \'fim\' para sair\n"); 
		unsigned int i;
	//UNICODE: Por defeito, a consola Windows não processa caracteres wide. 
	//A maneira mais fácil para ter esta funcionalidade é chamar _setmode:
#ifdef UNICODE 
	_setmode(_fileno(stdin), _O_WTEXT);
	_setmode(_fileno(stdout), _O_WTEXT);
#endif
	do {
		_tprintf(result);
		fflush(stdin);
		_fgetts(str, MAX, stdin); //fgets msdn -> _fgetts
		//Retirar \n 
		str[_tcslen(str) - 1] = '\0';
		//Maiúsculas 
		for (i = 0; i < _tcslen(str); i++)
			str[i] = _totupper(str[i]);

		_stprintf_s(result, MAX, TEXT("Frase:%s, Tamanho:%d\n"), str, _tcslen(str));
	} while (_tcsicmp(TEXT("FIM"), str));
	return 0;
}
//setlocale -> para lidar com os caracteres especiais em maiúsculas 

Os processos em Windows (child processes) CreateProcess (em linux era fork)

#include <windows.h>
#include <tchar.h>
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
#define MAX 256

int _tmain(int argc, LPTSTR argv[]) {
	TCHAR str[MAX], result[MAX] = TEXT("Olá! Este programa é para aceitar UNICODE. Insira \'fim\' para sair\n");
	unsigned int i;
#ifdef UNICODE 
	_setmode(_fileno(stdin), _O_WTEXT);
	_setmode(_fileno(stdout), _O_WTEXT);
#endif
	do {
		_tprintf(result);
		fflush(stdin);
		_fgetts(str, MAX, stdin); //fgets msdn -> _fgetts
		//Retirar \n 
		str[_tcslen(str) - 1] = '\0';
		//Maiúsculas 
		for (i = 0; i < _tcslen(str); i++)
			str[i] = _totupper(str[i]);

		_stprintf_s(result, MAX, TEXT("Frase:%s, Tamanho:%d\n"), str, _tcslen(str));
	} while (_tcsicmp(TEXT("FIM"), str));

	TCHAR texto[256] = TEXT("notepad");

	STARTUPINFO si; //
	PROCESS_INFORMATION pi; //

	//memset();
	ZeroMemory(&si, sizeof(si)); // mesmo que o memset mas com tudo a zero
	ZeroMemory(&pi, sizeof(pi)); // resultado da função: pid do processo, pid da threat principal do processo,
	//e handle (ponteiro para estrutura) do processo,  e handle para a thread principal
	//pid unico no sistema para cada processo, o handle podem ser vários, cada um com determinada permissão por exemplo
	
	si.cb = sizeof(STARTUPINFO); //tamanho da estrutura tem que estar preenchido, pelo menos esse!! .cb
		
	//criar um processo -> correr um programa que já foi compilado
	if (CreateProcess(NULL,   // No module name (use command line): se fosse o proprio -> argv[0] ou GetModuleFileName
		//argv[1],						       // Command line
		texto,
		NULL,				 // Process handle not inheritable
		NULL,					// Thread handle not inheritable
		FALSE,					// Set handle inheritance to FALSE
		0,						// No creation flags
		NULL,           // Use parent's environment block
		NULL,           // Use parent's starting directory 
		&si,            // Pointer to STARTUPINFO structure
		&pi)           // Pointer to PROCESS_INFORMATION structure
		)
	{
		_tprintf(TEXT("processo foi lançado PID: %d THREAD: %d"), pi.dwProcessId, pi.dwThreadId );
	}else
	{
		_tprintf("CreateProcess failed (%d).\n", GetLastError());
		return;
	}

	//esperar pelo processo terminar em linux: wait
	WaitForSingleObject(pi.hProcess, INFINITE); //ms >0 ou então quando terminar INFINITE
	//se for 0 só para consulta
	
	return 0;
}
Tags : , , ,

SO2 – Visão geral do sistemas Windows (“família NT”)

Windows família NT, principais características:
sistema de 32 bits / 64 bits
multiprogramado preemptivo reentrante
multi-thread
suporta uniprocessador e multiprocessador SMP

Os principais objectivos e impacto no desenvolvimento do SO:
extensibilidade
portabilidade
fiabilidade
compatibilidade
performance

A arquitectura do Windows NT é do tipo: cliente servidor (micro-kernel) e que tem como principais vantagens:
núcleo mais simples
maior fiabilidade
maior extensibilidade
maior adaptabilidade a computação distribuída (vários processadores)

Componentes do sistema:
parte em modo de utilizador (modo não privilegiado: subsistemas / servidores: proporcionam um ambiente de execução, de API, e integrais (por exemplo de segurança)
parte em modo de núcleo (modo de execução privilegiado)

Surge assim a estrutura do Windows NT:

As tarefas dos componentes do Executivo NT são:
gestão de processo e threads (escalonamento e despacho)
gestão das LPC (local procedures call)
gestão da memória do sistema /memória virtual
kernel, tratamento de interrupções e excepções
I/O, rede, sistemas de ficheiros, device drivers, gestor de cache
HAL, adaptação às especificidades das várias plataformas

A evolução na família NT teve em conta:
suporte para novo hardware
modelos dos device drivers
espaço de memória suportado
optimizações na comunicação com periféricos
interface com o utilizador
optimizações do processo de boot
modificações de subsistemas / modelos de programação

 

Tags : , ,

SO2 – apresentação

Bibliografia recomendada:
Windows System Programming, 4t edition, Johnson M. Hart, Addison Wesley, 2010
Windows NT4 Advanced Programming, Raj RajaGopal & Subodh Monica, Osborne McGraw-Hill
Windows NT programming, Herbert Schildt, Osborne McGraw Hill, 1997
Operating Systems Concepts, 6th edition, Silberschatz and Galvin, Addison-Wesley
Fundamentos de Sistemas Oeerativos, 3 edição, José Alves Marques, Paulo Guedes, Editorial Presença
Inside Windows NT, 2 edition, Microsoft PRess, 1998
Operating Systems: Internal and Design Principles, 3rd edition, William Stallings, Prentice-Hall, 1998
Structured Computer Organization, 4th edition, Andrew S, Tanenbaum, Prentice-Hall Internacional
The Design of the Unix Operating System, Maurice Bach, Prentice- Hall, 1999

Tags : , , ,