TAREFA (Task)
A. SENTIDO ABSTRATO. Designa a unidade fundamental de trabalho ou atividade que deve ser executada por um sistema de computação. Sob este aspecto, o termo é um gênero que abrange diversas espécies de execução, independentemente de serem implementadas como processos pesados, fios de execução (threads) ou rotinas de interrupção. "A task is a set of instructions that, when executed, provide a desired function." (C.M. KRISHNA; K.G. SHIN, Real-Time Systems, 1997).
B. SENTIDO TÉCNICO (Sistemas Operacionais). Do ponto de vista da gestão de recursos, a tarefa é a entidade à qual o escalonador (scheduler) atribui tempo de CPU. Neste sentido, confunde-se frequentemente com o conceito de contexto de execução. No núcleo Linux, por exemplo, a estrutura fundamental que representa qualquer fluxo de execução (seja ele um processo ou uma thread) é a task_struct.
C. SENTIDO FUNCIONAL (Programação e Fluxo de Trabalho). Refere-se a uma unidade lógica de processamento em sistemas de computação paralela ou distribuída. Por exemplo, em bibliotecas de Task-based Programming (como a TPL do .NET ou o Java Fork/Join), uma tarefa é uma promessa de computação que pode ser executada de forma assíncrona, abstraindo do programador a gestão direta das threads.
Crítica
A evolução da terminologia técnica na computação gerou uma sobreposição semântica entre Tarefa, Processo e Fio de Execução (Thread). Para afastar as confusões ou os sofismas, convém distinguir:
1º Tarefa vs. Processo
O processo é uma unidade de propriedade de recursos (espaço de endereçamento, descritores de arquivos); a tarefa é a unidade de execução. Na literatura clássica, como em Tanenbaum, o processo é o "recipiente", enquanto a tarefa (ou thread) é o "conteúdo" em movimento. "A process is an abstraction of a running program... The task is the activity associated with that process." (Andrew TANENBAUM, Modern Operating Systems).
2º Tarefa no Contexto de Sistemas de Tempo Real (RTOS)
Em sistemas de tempo real, a definição de tarefa assume um rigor matemático superior, sendo definida por um trio de parâmetros: $(\phi, T, C)$, onde $\phi$ é a fase (momento de chegada), $T$ o período e $C$ o tempo de execução no pior caso (Worst-Case Execution Time).
Observações
O desenvolvimento do núcleo Linux, sob a influência de Linus TORVALDS, evitou deliberadamente a distinção estrita entre processos e threads em nível de estrutura interna, optando pelo termo unificador task. Para o kernel, tanto um processo quanto uma thread são criados pela chamada de sistema clone(), diferenciando-se apenas pelo grau de compartilhamento de recursos (memória, sinais, etc.), sendo ambos instâncias da já mencionada task_struct. (Anônimo)
Exemplos
- Em linha de comando (Unix/Linux): O comando
topouhtopexibe o número de "Tasks" no topo da interface, indicando o total de fluxos de execução que o kernel está gerindo naquele instante (incluindo estados de running, sleeping, stopped e zombie). Em Programação Assíncrona (C#):
Task
minhaTarefa = Task.Run(() => { // Realiza uma computação pesada return 42;});
Aqui,
Taskrepresenta uma abstração de uma operação futura, cujo resultado será entregue sem que o programador precise manipular manualmente o ciclo de vida da CPU.Em Sistemas Embarcados (FreeRTOS):
xTaskCreate(vTaskCode, "NomeDaTarefa", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle);
Neste exemplo, a definição da tarefa é explicitamente uma função C que entrará na fila do escalonador de tempo real.