[OS] 프로세스 Part 1

희진·2024년 7월 12일
0
post-thumbnail

3.1 Process

  1. is a program in execution.

  2. is the unit of work in an operating system.

A process will need certain resources to accomplish its task.

CPU time, memory, files, I/O devices

The memory layout of a process

is divided into multiple sections

  1. Text Section: executable code

  2. Data Section: global variables

  3. Heap Section: memory that is dynamically allocated during program run time

  4. Stack Section: temporary data storage when invoking functions such as function parameters, return addresses, and local variables

#include <stdio.h>
#include <stdlib.h>

int x; // Uninitialized Data Section
int y = 15; // Initialized Data Section

// stack section
int main(int argc, char *argv[])
{
	int *values; // Stack Section
    int i; // Stack Section
    
    values = (int *)malloc(sizeof(int)*5); // Heap Section
    
    // Text Section
    for (i = 0; i < 5; i++)
    	values[i] = i;
    
    return 0;
}
Layout of a process in memorySize of sections

Process Lifecycle

  1. New: the process is being created by fork()
  2. Running: Instructions are being executed
  3. Waiting: the process is waiting for some event to occur
    such as an I/O completion or reception of a signal
  4. Ready: the process is waiting to be assigned to a processor
  5. Terminated: the process has finished execution

PCB(Process Control Block) or TCB(Task Control Block)

Each process is represented in the operating system by the PCB.

A PCB contains many pieces of information associated with a specific process

  1. Process state

  2. Program counter (Program counter Register → Instruction Register → fetch)

  3. CPU Registers

  4. CPU-scheduling information

  5. Memory-management information

  6. Accounting information

  7. I/O status information

A process is a program that performs a single thread of execution.

The single thread of control allows the process to perform
only one task at a time.

Moder operating systems have extended the process concept

  • to allow a process to have multiple threads of execution

  • and thus to perform more than one task at a time

A thread is a lightweight process

3.2 Process Scheduling

The objective of multiprogramming is to have some process running at all times (at the same time, simultaneously, concurrently)

The objective of multiprogramming is

to have some process running at all times so as to maximize CPU utilization

The objective of time sharing is

to switch a CPU core among processes so frequently that users can interact with each program while it is running

Scheduling Queues (for time sharing)

As processes enter the system, they are put into a ready queue where they are ready and waiting to execute on a CPU's core.

Processes that are waiting for a certain event to occur are placed in a wait queue. (and in a ready queue, not in a running queue)

Queueing Diagram

as a common representation of process scheduling.

Context Switch (by OS)

The context of a process is represented in the PCB. (PCB information == context)

When an interrupt occurs

  1. the system saves the current context of the running process,

  2. so that, later, it can restore that context when it should be resumed.

The context switch is a task that

  1. switches the CPU core to another process

  2. performs a state save of the current process

  3. and a state restore of a different process.

3.3 Operations on Processes

An operating system must provide a mechanism for

  1. process creation

  2. process termination

A process may create several new processes (by fork())

  • the creating process: a parent process

  • a newly created process: a child process

Two possibilities for execution

  1. The parent continues to execute concurrently with its children.

  2. The parent waits until some or all of its children have terminated.

Two possibilities of address-space

The child process is a duplicate of the parent process.

The child process has a new program loaded into it.

#include <stdio.h>
#include <unistd.h>
#include <wait.h>

// Creating a separate process using the UNIX fork() system call.

int main()
{
	pid_t pid; // pid(process Id)
    // fork a child process
    pid = fork(); // return new pid
    if (pid < 0) { // error occurred
    	fprintf(stderr, "Fork Failed");
        return 1;
    }
    else if (pid == 0) { // child process
    	execlp("/bin/ls", "ls", NULL);
    }
    else { // parent process, pid > 0
    	wait(NULL);
        printf("Child Complete");
    }
    return 0;
}

* pid의 값에 따라 달라짐

Terminate Process

  • A process terminates when it finished executing its final statement

  • exit() system call: asks OS to delete it

  • OS dellocates and reclaims all the resources

    	allocated momeries, open files, and I/O buffers, etc.

Zombie and Orphan

zombie process (...background process)

a process that has terminated, but whose parent has not yet called wait().

orphan process (...daemon process)

a process that has a parent process who did not invoke wait() and instead terminated.

UNIX-like O/S

A new process is created by the fork() system call.

The child process consists of a copy of the address space of the parent process

Both processes continue execution at the instruction after the fork() system call

With one difference:

  • the return code for the fork() is zero for the child process.

  • the nonzero pid of the child is returned to the parent process.

#include <stdio.h>
#include <unistd.h>

int main()
{
	pid_t pid;
    pid = fork();
    printf("Hello, Process!\n");
    
    return 0
}

Output

Hello, Process!
Hello, Process!
#include <stdio.h>
#include <unistd.h>

int main()
{
	pid_t pid;
    pid = fork();
    printf("Hello, Process! %d\n", pid);
    
    return 0
}

Output

Hello, Process! 2547
Hello, Process! 0

After a fork() system call

  1. the parent can continue its execution

  2. or if it has nothing else to do while the child runs, it can issue a wait() system call to move itself off the ready queue until the termination of the child.

#include <stdio.h>
#include <unistd.h>
#include <wait.h>

int main()
{
	pid_t pid;
    pid = fork();
    if (pid > 0) // parent process
    	wait(NULL);
    printf("Hello, Process! %d\n", pid);
}

Output

Hello, Process! 0
Hello, Process! 3004

Excercise 3.1 (p.154)

// What output will be at Line A?
int value = 5;

int main()
{
	pid_t pid;
    pid = fork();
    
    if (pid == 0) { // chile process
    	value += 15;
        return 0;
    }
    else if (pid > 0) { // parent process
    	wait(NULL);
        printf("Parent: value = %d\n", value); // Line A
    }
}

Output

Parent: value = 5

Excercise 3.2 (p.154)

#include <stdio.h>
#include <unistd.h>
#include <wait.h>

// How many processes are created?
int main()
{
	fork(); // fork a child process
    fork(); // fork another child process
    fork(); // and fork another
    
    return 0;
}

Output

Parent: value = 5

Excercise 3.11 (p.905)

#include <stdio.h>
#include <unistd.h>

// How many processes are created?
int main()
{
	int i;
    pid_t pid;
    
    for (i = 0; i < 4; i++) // 4 times
    	pid = fork();

    printf("Hello, Fork\n");

	return 0;
}

Output

16 times print

Self-Study

#include <stdio.h>
#include <unistd.h>
#include <wait.h>

int value = 5;

// How many processes are created?
int main()
{
	fork(); // fork a child process
    value += 5;
    fork(); // fork another child process
    value += 5;
	fork(); // and fork another
    value += 5;
    printf("Hello, Fork() %d\n", value);

    return 0;
}
#include <stdio.h>
#include <unistd.h>

// How many processes are created?
int main()
{
	int i;
    pid_t pid;
    
    for (i = 0; i < 4; i++) // 4 times
    	pid = fork();

    printf("Hello, Fork %d\n", pid);

	return 0;
}

Excercise 3.12 (p.905)

// When will LINE J be reached?

int main()
{
	pid_t pid;
    pid = fork();
    
    if (pid == 0) { // child process
    	execlp("/bin/ls", "ls", NULL); // execlp: 새로운 실행 파일 "ls"로 로드
        printf("LINE J\n"); // 무시
    }
    else if (pid > 0) { // parent process
    	wait(NULL);
        printf("Child Complete\n");
	}
    
    return 0;
}
// What are the pid values?
int main()
{
	pid_t pid, pid1;
    pid = fork();
    if (pid == 0) { // child process
    	pid1 = getpid();
        printf("child: pid = %d\n", pid); // A
        printf("child: pid1 = %d\n", pid1); // B
    }
    else if (pid > 0) { // parent process
    	wait(NULL);
    	pid1 = getpid();
        printf("child: pid = %d\n", pid); // C
        printf("child: pid1 = %d\n", pid1); // D
	}
    return 0;
}

Output

child: pid = 0 // A
child: pid1 = 5278 // B
child: pid = 5278 // C
child: pid1 = 5277 // D

Excercise 3.16 (p.905)

#define SIZE 5
int nums[SIZE] = {0, 1, 2, 3, 4};

// What output will be at Line X and Line Y?
int main()
{
	pid_t pid;
    int i;
    pid = fork();
    
    if (pid == 0) { // child process
    	for (i = 0; i < SIZE; i++) {
        	nums[i] *= i;
            printf("CHILD: %d \n", nums[i]); // LINE X
		}
	}
    else if (pid > 0) { // parent process
    	wait(NULL);
        for (i = 0; i < SIZE; i++) {
        	printf("PARENT: %d \n", nums[i]); // LINE Y
		}
	}
    return 0;
}

Output

PARENT: 0
PARENT: 1
PARENT: 2
PARENT: 3
PARENT: 4
CHILD: 0
CHILD: 1
CHILD: 4
CHILD: 9
CHILD: 16
profile
열심히 살겠습니다

0개의 댓글