CPU Hotplug를 지원하는 배터리 세이버가 없나요?

frech의 이미지

외장그래픽이 달린 노트북을 쓰는데 bumblebee로 외장 그래픽을 쓰고요, laptop-mode-tools나 tlp를 사용하면 wayland 환경 아래에서 자동으로 외장그래픽을 지원하는 프로그램이 외장그래픽을 사용해서 제가 직접 꺼줘야 하는 불편함이 생겨서 사용에 어려움이 있어서 사용을 못하고 있습니다.
위에 두 프로그램을 못 쓰다 보니까 배터리가 살살 녹아서 cpu덜 돌리면 배터리 적게 든다는 것 밖에 몰라 cpu hotplug를 하는 데몬을 만들어 쓰고 있습니다.
혹시 cpu hotplug를 지원하는 데몬이나 위에 배터리 세이버 말고 다른 프로그램은 알고 계신게 없는지 궁금합니다.

그리고 cpu hotplug를 파일 시스템을 통해서 말고 C api로 되어 있는게 없는지도 궁금합니다. 인터넷에는 잘 나오지 않네요.

#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/fs.h>
#include <sys/sysinfo.h>
 
void hotplug_cpu(unsigned short id, unsigned short check) { //id번 시피유 끄기
	char* status;
	if (check == 0 ) status = "0";
	else status = "1";
 
	char cpu[36];
	sprintf(cpu, "/sys/devices/system/cpu/cpu%d/online", id);
	int fd = open(cpu, O_RDWR );
 
	if (!write(fd, status, 2)) printf("failed to turn on/off cpu%d\n", id);
 
	close (fd);
}
 
void turbo_controller(unsigned short check) { //터보 부스트 제어
	char* status;
	if (check == 0) status = "1";
	else status = "0";
 
	int fd = open("/sys/devices/system/cpu/intel_pstate/no_turbo", O_RDWR);
 
	if (!write(fd, status, 2)) printf("failed to turn on/off turbo boost\n");
 
	close(fd);
}
 
int main(void) {
 
	pid_t pid;
	int i;
 
	pid = fork();
	if (pid == -1) {
		printf("fork\n");
		return -1;
	}
 
	if (pid != 0) exit(EXIT_SUCCESS);
 
	if (setsid() == -1) return -1;
 
	open("/dev/null", O_RDWR);
	dup(0);
	dup(0);
 
	unsigned short cpus = get_nprocs_conf();
	unsigned short energy_model = cpus / 3;
	unsigned short balance_model = 2 * energy_model;
 
	FILE* fp;
	int user, nice, system, idle, iowait, irq, softirq;
	int sum;
	float usage;
 
	unsigned short state = 0; // 0 energy safe model, 1 balanced model, 2 performance balanced model 3 performance mode
 
	fp = fopen("/proc/stat", "r");
        if (fp == NULL) {
        	printf ("failed to get stat\n");
        	exit(1);
        }
        fscanf(fp, "cpu  %d %d %d %d %d %d %d", &user, &nice, &system, &idle, &iowait, &irq, &softirq);
        fclose(fp);
 
	sleep(1);
 
	while(1) {
		int current_user;
		int current_system;
		fp = fopen("/proc/stat", "r");
		if (fp == NULL) {
			printf ("failed to get stat\n");
			exit(1);
		}
		fscanf(fp, "cpu  %d %d %d %d %d %d %d", &current_user, &nice, &current_system, &idle, &iowait, &irq, &softirq);
                fclose(fp);
		int current_sum = current_user + nice + system + idle + iowait + irq + softirq;
		int user_res = current_user - user;
		int system_res = current_system - system;
		int current_state;
		usage = (float)(user_res + system_res)/(current_sum - sum)*100;
		if ( usage < 5 ) { // 사용률 퍼센트로 계산해서 제어
			current_state = 0;	
		} else if (usage < 20 ) {
			current_state = 1;
		} else if (usage < 50 ) {
			current_state = 2;
		} else current_state = 3;
 
		if (current_state != state) {
 
			if (current_state == 0) {
				for ( int i = cpus-1;i > energy_model-1;i--) {
					hotplug_cpu(i + 6, 0);
					hotplug_cpu(i, 0);
				}
				turbo_controller(0);
			} else if (current_state == 1) {
				for ( int i = cpus-1;i > balance_model-1;i--) {
					hotplug_cpu(i + 6, 0);
					hotplug_cpu(i, 0);
				}
				for ( int i = balance_model-1;i > energy_model-1;i--) {
					hotplug_cpu(i, 1);
					hotplug_cpu(i + 6, 1);
				}
				turbo_controller(0);
			} else if (current_state == 2) {
				for ( int i = cpus-1;i > balance_model-1;i--) {
                                        hotplug_cpu(i + 6, 0);
                                        hotplug_cpu(i, 0);
                                }
                                for ( int i = balance_model-1;i > energy_model-1;i--) {
                                        hotplug_cpu(i, 1);
                                        hotplug_cpu(i + 6, 1);
                                }
                                turbo_controller(1);
			} else  {
				for (int i = cpus-1;i > 1;i--) {
					hotplug_cpu(i, 1);
					hotplug_cpu(i + 6, 1);
				}
				turbo_controller(1);
			}
 
			state = current_state;
 
		};
 
		sum = current_sum;
		user = current_user;
		system = current_system;
 
		sleep(1);
	}
 
	return 0;
}