`pthread_mutex_init(program.write_lock, NULL);`에서 `NULL`을 할당하는 것은 뮤텍스를 초기화할 때 **기본 속성**을 사용하겠다는 의미입니다. `pthread_mutex_init` 함수는 뮤텍스를 초기화하는 데 사용되며, 두 번째 매개변수로 뮤텍스의 속성을 지정할 수 있습니다. 이 매개변수에 `NULL`을 전달하면 뮤텍스는 기본 속성으로 초기화됩니다.
---
### **`pthread_mutex_init` 함수의 구문**
```c
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
```
1. **`mutex`**:
- 초기화할 뮤텍스의 포인터입니다.
2. **`attr`**:
- 뮤텍스의 속성을 지정하는 `pthread_mutexattr_t` 구조체의 포인터입니다.
- `NULL`을 전달하면 뮤텍스는 기본 속성으로 초기화됩니다.
---
### **`NULL`을 할당하는 의미**
- **기본 속성 사용**:
- `NULL`을 전달하면 뮤텍스는 기본 속성으로 초기화됩니다.
- 기본 속성은 일반적으로 다음과 같은 특징을 가집니다:
- **비재진입(non-recursive)**: 같은 스레드가 뮤텍스를 중복으로 잠글 수 없습니다.
- **프로세스 간 공유 불가**: 뮤텍스는 같은 프로세스 내의 스레드들만 공유할 수 있습니다.
- **간단한 사용**:
- 특별한 속성이 필요하지 않은 경우 `NULL`을 사용하여 뮤텍스를 초기화하면 코드가 간결해집니다.
- 대부분의 경우 기본 속성으로 충분합니다.
---
### **뮤텍스 속성 커스터마이징**
만약 뮤텍스에 특별한 속성을 부여하고 싶다면 `pthread_mutexattr_t` 구조체를 사용하여 속성을 설정할 수 있습니다. 예를 들어:
1. **재진입 가능한 뮤텍스(recursive mutex)**:
- 같은 스레드가 뮤텍스를 중복으로 잠글 수 있습니다.
- `pthread_mutexattr_settype` 함수를 사용하여 설정합니다.
2. **프로세스 간 공유 가능한 뮤텍스**:
- 뮤텍스를 다른 프로세스와 공유할 수 있습니다.
- `pthread_mutexattr_setpshared` 함수를 사용하여 설정합니다.
---
### **예시: 기본 속성으로 뮤텍스 초기화**
```c
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL); // 기본 속성으로 뮤텍스 초기화
```
---
### **예시: 커스터마이징된 속성으로 뮤텍스 초기화**
```c
pthread_mutex_t mutex;
pthread_mutexattr_t attr;
// 뮤텍스 속성 초기화
pthread_mutexattr_init(&attr);
// 재진입 가능한 뮤텍스로 설정
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
// 뮤텍스 초기화 (커스터마이징된 속성 사용)
pthread_mutex_init(&mutex, &attr);
// 뮤텍스 속성 해제
pthread_mutexattr_destroy(&attr);
```
---
### **결론**
- `pthread_mutex_init(program.write_lock, NULL);`에서 `NULL`은 뮤텍스를 기본 속성으로 초기화하겠다는 의미입니다.
- 기본 속성은 일반적인 경우에 충분하며, 특별한 속성이 필요한 경우 `pthread_mutexattr_t`를 사용하여 커스터마이징할 수 있습니다.
- `NULL`을 사용하면 코드가 간결해지고, 대부분의 경우 기본 속성으로 충분하므로 널리 사용됩니다.
`init_philos` 함수는 철학자 문제(Dining Philosophers Problem)에서 각 철학자(`t_philo`)의 상태와 속성을 초기화하는 역할을 합니다. 이 함수는 철학자의 ID, 식사 상태, 포크(뮤텍스) 할당, 공유 자원(뮤텍스 및 플래그) 설정 등을 수행합니다. 아래에서 이 함수를 상세히 설명하겠습니다.
---
### **함수의 매개변수**
1. **`t_philo *philos`**:
- 철학자들의 정보를 저장할 배열입니다. 각 철학자는 `t_philo` 구조체로 표현됩니다.
2. **`t_program *program`**:
- 프로그램 전체의 상태와 공유 자원을 관리하는 구조체입니다. 여기서는 뮤텍스와 플래그를 공유합니다.
3. **`pthread_mutex_t *forks`**:
- 철학자들이 사용할 포크(뮤텍스) 배열입니다. 각 포크는 철학자들이 공유하는 자원입니다.
4. **`char **argv`**:
- 프로그램 실행 시 전달된 인자들입니다. 철학자의 수, 시간 설정 등을 포함합니다.
---
### **함수의 동작**
1. **철학자 배열 초기화**:
- `while` 루프를 사용하여 철학자 배열(`philos`)을 초기화합니다.
- 각 철학자의 ID, 식사 상태, 식사 횟수, 시작 시간, 마지막 식사 시간 등을 설정합니다.
2. **입력 값 초기화**:
- `init_input` 함수를 호출하여 철학자의 시간 설정(`time_to_die`, `time_to_eat`, `time_to_sleep`)을 초기화합니다.
3. **공유 자원 설정**:
- 철학자가 공유하는 뮤텍스와 플래그를 설정합니다.
- `write_lock`: 출력 동기화를 위한 뮤텍스.
- `dead_lock`: 철학자의 죽음 상태를 보호하는 뮤텍스.
- `meal_lock`: 철학자의 식사 상태를 보호하는 뮤텍스.
- `dead`: 철학자의 죽음 상태를 나타내는 플래그.
4. **포크 할당**:
- 각 철학자에게 왼쪽 포크와 오른쪽 포크를 할당합니다.
- 첫 번째 철학자의 오른쪽 포크는 마지막 철학자의 포크와 동일합니다 (원형 테이블 구조).
---
### **코드 상세 설명**
```c
void init_philos(t_philo *philos, t_program *program, pthread_mutex_t *forks, char **argv)
{
int i;
i = 0;
while (i < ft_atoi(argv[1])) // 철학자의 수만큼 반복
{
// 철학자의 기본 정보 설정
philos[i].id = i + 1; // 철학자의 ID (1부터 시작)
philos[i].eating = 0; // 철학자의 식사 상태 (0: 먹지 않음)
philos[i].meals_eaten = 0; // 철학자가 먹은 식사 횟수 (초기값 0)
init_input(&philos[i], argv); // 철학자의 시간 설정 초기화
// 시간 관련 정보 설정
philos[i].start_time = get_current_time(); // 프로그램 시작 시간
philos[i].last_meal = get_current_time(); // 마지막 식사 시간 (초기값은 현재 시간)
// 공유 자원 설정
philos[i].write_lock = &program->write_lock; // 출력용 뮤텍스
philos[i].dead_lock = &program->dead_lock; // 죽음 상태 보호용 뮤텍스
philos[i].meal_lock = &program->meal_lock; // 식사 상태 보호용 뮤텍스
philos[i].dead = &program->dead_flag; // 철학자의 죽음 상태 플래그
// 포크 할당
philos[i].l_fork = &forks[i]; // 왼쪽 포크
if (i == 0)
philos[i].r_fork = &forks[philos[i].num_of_philos - 1]; // 첫 번째 철학자의 오른쪽 포크는 마지막 철학자의 포크
else
philos[i].r_fork = &forks[i - 1]; // 나머지 철학자의 오른쪽 포크
i++;
}
}
```
---
### **초기화 과정의 주요 포인트**
1. **철학자의 ID**:
- 철학자의 ID는 1부터 시작합니다. 이는 출력 시 철학자를 구분하는 데 사용됩니다.
2. **시간 설정**:
- `init_input` 함수는 `argv`를 기반으로 철학자의 `time_to_die`, `time_to_eat`, `time_to_sleep` 등을 설정합니다.
3. **공유 자원**:
- 모든 철학자는 `program` 구조체의 뮤텍스와 플래그를 공유합니다. 이를 통해 철학자 간의 동기화가 이루어집니다.
4. **포크 할당**:
- 철학자들은 원형 테이블에 앉아 있으므로, 첫 번째 철학자의 오른쪽 포크는 마지막 철학자의 포크와 동일합니다.
---
### **예시: 철학자 5명 초기화**
1. **입력**:
- `argv[1] = "5"` (철학자 수)
- `argv[2] = "800"` (time_to_die)
- `argv[3] = "200"` (time_to_eat)
- `argv[4] = "200"` (time_to_sleep)
2. **초기화 결과**:
- 철학자 1: 왼쪽 포크 = `forks[0]`, 오른쪽 포크 = `forks[4]`
- 철학자 2: 왼쪽 포크 = `forks[1]`, 오른쪽 포크 = `forks[0]`
- 철학자 3: 왼쪽 포크 = `forks[2]`, 오른쪽 포크 = `forks[1]`
- 철학자 4: 왼쪽 포크 = `forks[3]`, 오른쪽 포크 = `forks[2]`
- 철학자 5: 왼쪽 포크 = `forks[4]`, 오른쪽 포크 = `forks[3]`
---
### **결론**
- `init_philos` 함수는 철학자 문제에서 각 철학자의 상태와 속성을 초기화합니다.
- 철학자의 ID, 시간 설정, 공유 자원, 포크 할당 등을 설정하여 철학자 문제를 해결할 준비를 합니다.
- 이 함수는 철학자 문제의 핵심 로직을 구현하기 위한 기반을 제공합니다.
'C Language' 카테고리의 다른 글
pthread_create pthread_join 설명 (0) | 2025.03.12 |
---|---|
pthread_mutex_lock unlock (0) | 2025.03.10 |
mutex (0) | 2025.03.10 |
cpp 01 (0) | 2025.03.10 |
minishell01 (0) | 2025.03.08 |