C에서 sched_setaffinity 함수 사용
이 기사에서는 C에서sched_setaffinity
함수를 사용하는 방법에 대한 몇 가지 방법을 설명합니다.
sched_setaffinity
함수를 사용하여 프로세스 실행을 특정 CPU로 제한
오늘날 멀티 코어 하드웨어는 어디에나 있으며 운영 체제는 이러한 코어에서 동시에 실행되는 여러 프로세스를 관리해야합니다. 프로세스 / 스레드 실행을 관리하는 운영 체제 부분을 스케줄러라고합니다. 스케줄러는 모든 기존 프로세스 / 스레드를 사용 가능한 코어에 효율적으로 배포하고 그에 따라 시간 조각을 할당하려고합니다. 스케줄링은 주어진 시스템에 대한 주요 성능 보장이기 때문에 운영 체제에서 가장 어려운 설계 문제 중 하나입니다. 스케줄러와 상호 작용하는 표준 C 인터페이스는 없지만 특정 OS는 여러 프로세스 스케줄링 매개 변수를 수정하기위한 시스템 호출을 제공합니다.
sched_setaffinity
는 GNU C 라이브러리의 일부이며 대부분 Linux 관련 기능을 기반으로합니다. 이 함수는 프로세스가 실행될 수있는 CPU 코어 세트를 나타내는 소위 CPU 선호도 마스크를 설정합니다. sched_setaffinity
는 첫 번째 인자로 PID 값을, 두 번째 인자로sizeof(cpu_set_t)
를 취합니다. 세 번째 인수는cpu_set_t
유형이며<sched.h>
헤더의 사전 정의 된 매크로를 사용하여 조작해야하는 불투명 구조입니다. 그러나_GNU_SOURCE
매크로는 이러한 함수와 매크로를 사용할 수 있도록 정의해야합니다. 다음 예제에서는 사용자로부터 세 개의 정수를 명령 줄 인수로 가져 와서 부모 / 자식 프로세스 CPU 번호와 여러 루프 반복을 각각 나타 내기 위해 저장하는 프로그램을 구현합니다. 그런 다음CPU_ZERO
매크로를 사용하여cpu_set_t
변수를 지우고fork
를 호출하여 자식 프로세스를 생성합니다.
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#define errExit(msg) \
do { \
perror(msg); \
exit(EXIT_FAILURE); \
} while (0)
int main(int argc, char *argv[]) {
cpu_set_t set;
int parentCPU, childCPU, wstatus;
long nloops;
if (argc != 4) {
fprintf(stderr, "Usage: %s parent-cpu child-cpu num-loops\n", argv[0]);
exit(EXIT_FAILURE);
}
parentCPU = strtol(argv[1], NULL, 0);
childCPU = strtol(argv[2], NULL, 0);
nloops = strtol(argv[3], NULL, 0);
CPU_ZERO(&set);
switch (fork()) {
case -1:
errExit("fork");
case 0:
CPU_SET(childCPU, &set);
if (sched_setaffinity(getpid(), sizeof(set), &set) == -1)
errExit("sched_setaffinity");
for (int j = 0; j < nloops; j++) getpid();
exit(EXIT_SUCCESS);
default:
CPU_SET(parentCPU, &set);
if (sched_setaffinity(getpid(), sizeof(set), &set) == -1)
errExit("sched_setaffinity");
for (int j = 0; j < nloops; j++) getpid();
wait(NULL);
exit(EXIT_SUCCESS);
}
}
CPU_SET
매크로를 사용하여 프로세스를 바인딩 할 CPU 코어를 지정합니다
sched_setaffinity
함수는 프로세스 또는 스레드별로 호출됩니다. 따라서 ‘fork’가 반환되면 부모 및 자식 프로세스에 대해 다른 CPU 마스크를 지정할 수 있습니다. CPU_SET
매크로는 이전에 비워진cpu_set_t
구조를 수정하고 결과적으로sched_setaffinity
호출에 전달하는 데 사용됩니다. 각 프로세스는 ‘getpid’를 호출하는 루프를 실행하여 CPU 리소스를 차지하고 예제를 더 쉽게 보여줄 수 있습니다. 부모 프로세스는 이전 예제에서wait
호출을 사용하고 다음 예제에서waitpid
를 사용하여 자식을 기다립니다. 시연 된 동작을 관찰하려면 Linux 시스템에서 널리 사용되는htop
명령 줄 유틸리티를 사용하여 시스템 프로세스를 관찰 할 수 있습니다.
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#define errExit(msg) \
do { \
perror(msg); \
exit(EXIT_FAILURE); \
} while (0)
int main(int argc, char *argv[]) {
cpu_set_t set;
int parentCPU, childCPU, wstatus;
long nloops;
if (argc != 4) {
fprintf(stderr, "Usage: %s parent-cpu child-cpu num-loops\n", argv[0]);
exit(EXIT_FAILURE);
}
parentCPU = strtol(argv[1], NULL, 0);
childCPU = strtol(argv[2], NULL, 0);
nloops = strtol(argv[3], NULL, 0);
CPU_ZERO(&set);
pid_t c_pid = fork();
if (c_pid == -1) errExit("fork");
switch (c_pid) {
case -1:
errExit("fork");
case 0:
CPU_SET(childCPU, &set);
if (sched_setaffinity(getpid(), sizeof(set), &set) == -1)
errExit("sched_setaffinity");
for (int j = 0; j < nloops; j++) getpid();
exit(EXIT_SUCCESS);
default:
CPU_SET(parentCPU, &set);
if (sched_setaffinity(getpid(), sizeof(set), &set) == -1)
errExit("sched_setaffinity");
for (int j = 0; j < nloops; j++) getpid();
if (waitpid(c_pid, &wstatus, WUNTRACED | WCONTINUED) == -1)
errExit("waitpid");
exit(EXIT_SUCCESS);
}
}
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook