C语言实现android中内存和CPUUsage的控制(同样适用于任何linux设备)

来源:互联网 发布:macbook 上必备软件 编辑:程序博客网 时间:2024/05/29 08:04

Name: Background tool
Descroption: manage android memory and CPU usage.
Preparation: 
1. download BGMonitor and BGManager and push them into /system/bin.
2. chmod 777.
Usage:
1. Malloc some memory.
1.1 Format: BGManager -m [size(Mb)]
1.2 Example: BGManager -m 100
1.3 Explain: system will malloc 100Mb
2. remain some memory.
2.1 Format: BGManager -r [size(Mb)]
2.2 Example: BGManager -r 200
2.3 Explain: memory will remain 200Mb
3. spawn process.
3.1 Format: BGManager -c [number]
3.2 Example: BGManager -c 20
3.3 Explain: system will spawn 20 new processes
4. stop all processes and free all memory.
4.1 Format: BGManager -m/-r/-c -1
Note:
1. BGMonitor must be pushed into /system/bin though we would never run it.
2. If system hang after running BGmanager, please execute "rm /data/.my_fifo*" and try again.
Open issue:
1. system hang when exiting BGMonitor service when only 1 process spawned.
Steps: a. execute "BGManager -c 1".
             b. execute "BGManager -c -1".
Result: system hang.

2. system will remain at least 7-10M memory though executing "BGManager -r 0". And the reason of this issue is the android low memory mechanism. 


BG_server.c源码

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>//#define FIFO_CHANNEL "./.my_fifo"  //#define FIFO_CHANNEL_2 "./.my_fifo_2"  #define FIFO_CHANNEL "/data/.my_fifo"#define FIFO_CHANNEL_2 "/data/.my_fifo_2"#define MBUNIT 1000000#define KBUNIT 1000#define STATE_TRANSITION_IS(curr_s, next_s) ((curr_state == curr_s) && (next_state == next_s))enum {STATE_INIT,STATE_NORMAL,};void* mem_region_start;long long occupiedMem = 0;char* getStateName(int s) {switch(s) {case STATE_INIT:return "STATE_INIT";case STATE_NORMAL:return "STATE_NORMAL";default:return NULL;}}void delete_char(char *source, char c){int i, j, len;len = strlen(source);for(i=0; i<len; i++){if(source[i] == c)    {for(j=i;j<(len-1);j++)source[j]=source[j+1];len--;source[len] = '\0';    }}}void delete_everyChar(char *source, char *deleteChar){int i, len;len = strlen(deleteChar);for (i=0; i<len; i++){delete_char(source, deleteChar[i]);}}long long getCurrFreeMem() {FILE *stream;char buf[1024];long size;memset(buf, '\0', sizeof(buf));stream = popen("cat /proc/meminfo | grep MemFree", "r");fread(buf, sizeof(char), sizeof(buf), stream);pclose(stream);fprintf("%s", stderr, buf); delete_everyChar(buf, "MemFree:kB ");size = atoll(buf);return size;}void state_machine(long long size) {int curr_state, next_state;(mem_region_start == NULL)? (curr_state = STATE_INIT): (curr_state = STATE_NORMAL);switch(curr_state) {case STATE_INIT:if(size > 0) {next_state = STATE_NORMAL;}else {  //size==0next_state = STATE_INIT;}break;case STATE_NORMAL:if(size == 0) {next_state = STATE_INIT;}else {   //(size > 0)next_state = STATE_NORMAL;}break;}//fprintf(stderr,"%s -> %s\n", getStateName(curr_state), getStateName(next_state));if(STATE_TRANSITION_IS(STATE_INIT, STATE_INIT)) {//do nothing}else if(STATE_TRANSITION_IS(STATE_NORMAL, STATE_INIT)) {free(mem_region_start);mem_region_start = NULL;occupiedMem = 0;//fprintf(stderr,"free memory\n");}else if(STATE_TRANSITION_IS(STATE_INIT, STATE_NORMAL)) {mem_region_start = NULL;mem_region_start = malloc(size);memset(mem_region_start, 0xff, size);occupiedMem = size;//fprintf(stderr,"init %x len:%d\n", mem_region_start, size);}else if(STATE_TRANSITION_IS(STATE_NORMAL, STATE_NORMAL)) {free(mem_region_start);mem_region_start = NULL;mem_region_start = malloc(size);memset(mem_region_start, 0xff, size);occupiedMem = size;//fprintf(stderr,"resize to %x len:%d\n", mem_region_start, size);}}long FIFO_read() {int ret;int fd;char buf[128];memset(buf, 0, sizeof buf);if((fd=open(FIFO_CHANNEL,O_RDONLY)) < 0) {perror("Cannot open the FIFO");return -1;}if(ret=read(fd, buf, sizeof buf) < 0){perror("Cannot read content from FIFO");close(fd);return -1;}//printf("%s %s\n", __FUNCTION__, buf);close(fd);return atol(buf);}int FIFO_read_2() {int ret;int fd;char buf[4];memset(buf, 0, sizeof buf);if((fd=open(FIFO_CHANNEL_2,O_RDONLY)) < 0) {perror("Cannot open the FIFO");return -1;}if(ret=read(fd, buf, sizeof buf) < 0){perror("Cannot read content from FIFO");close(fd);return -1;}//printf("%s %s\n", __FUNCTION__, buf);close(fd);return atoi(buf);}int main() {fprintf(stderr, "To stop server: just start a client and send -1\n");unlink(FIFO_CHANNEL);unlink(FIFO_CHANNEL_2);if(mkfifo(FIFO_CHANNEL,0777) < 0) {perror("Cannot create FIFO channel");return -1;}if(mkfifo(FIFO_CHANNEL_2,0777) < 0) {perror("Cannot create FIFO channel_2");return -1;}while(1) {long size = 0;int type = 0;size = FIFO_read();type = FIFO_read_2();if (size == -1) {fprintf(stderr, "BGMonitor service stop\n");free(mem_region_start);break;}else if(size < -1) {fprintf(stderr, "Cannot input negetive value\n");}else{if(type == 1 || type == 2){if(size >= 0) {fprintf(stderr, "--------------------------------------\n");fprintf(stderr, "Before malloc:\n");long currFreeMem = getCurrFreeMem();//fprintf(stderr, "malloc %d\n", size);if (type == 1) {if (size >= 8000 || (size * KBUNIT) >= (currFreeMem + occupiedMem/KBUNIT)) {fprintf(stderr, "Cannot malloc, not enough memory\n");}else {state_machine(size * MBUNIT);}}else {if (size < 8000) {int checkSize = currFreeMem + occupiedMem/KBUNIT - size * KBUNIT;if (checkSize < 0) {fprintf(stderr, "Cannot malloc, not enough memory\n");}else {size = currFreeMem * KBUNIT + occupiedMem - size * MBUNIT;state_machine(size);}}else {fprintf(stderr, "Cannot malloc, not enough memory\n");}}fprintf(stderr, "After malloc: \n");fprintf(stderr, "MemOccupied:  %lld kB\n", occupiedMem/KBUNIT);getCurrFreeMem();fprintf(stderr, "\nPress ENTER to quit and send -1 to stop server and other process.\n");}else {fprintf(stderr, "Cannot input negetive value\n");}}else if(type == 3){int pid, i;for(i=1;i<=size;i++){pid = fork();if (pid < 0){fprintf(stderr, "error while forking.\n");exit(-1);}else if (pid == 0){int a;fprintf(stderr, "One process generated.\n");if(access("/data/.flag", 0) != 0) {system("touch /data/.flag");}while(1){if(access("/data/.flag", 0) != 0) {break;}else {a = sqrt(2);}}exit(0);}else{;}}}else{perror("Unknown command type");exit(-1);}}} unlink(FIFO_CHANNEL);unlink(FIFO_CHANNEL_2);return 0;}

BG_client.c源码

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>//#define FIFO_CHANNEL "./.my_fifo"  //#define FIFO_CHANNEL_2 "./.my_fifo_2"  #define FIFO_CHANNEL "/data/.my_fifo"#define FIFO_CHANNEL_2 "/data/.my_fifo_2"int type = 0;int create_server() {int i = system("/system/bin/BGMonitor");if (i != 0) {perror("Cannot find BG server binary!");return -1;}return 0;}int send_to_server(long size) {int ret = 0;int fd;char buf[128];char buf_2[4];memset(buf, 0, sizeof buf);memset(buf_2, 0, sizeof buf_2);if((fd=open(FIFO_CHANNEL,O_WRONLY))==-1) {perror("Cannot open the FIFO");return -1;}sprintf(buf, "%ld", size);if(ret=write(fd, buf, strlen(buf)) < 0){perror("Cannot write to FIFO");close(fd);}if((fd=open(FIFO_CHANNEL_2,O_WRONLY))==-1) {perror("Cannot open the FIFO_2");return -1;}sprintf(buf_2, "%d", type);if(ret=write(fd, buf_2, strlen(buf_2)) < 0){perror("Cannot write to FIFO_2");close(fd);}//printf("%s %s\n", __FUNCTION__, buf);close(fd);return 0;}int main(int argc, char *argv[]) {long size;if(argc != 3) { fprintf(stderr,"USAGE:\n./MemManager [type(-m, -r, -c)] [size(M)/num]\nINTRO:\n-m: memory will malloc [size]Mb.\n-r: memory will remain [size]Mb.\n-c: system will spawn [num] process (cost 50\% CPU per process).\n"); return -1;}if (strcmp(argv[1], "-m") == 0) {type = 1;}else if (strcmp(argv[1], "-r") == 0) {type = 2;}else if (strcmp(argv[1], "-c") == 0) {type = 3;}else { fprintf(stderr,"only support -m, -r and -c!\n"); exit(-1);}size = atol(argv[2]);if (size <= -1){size = -1;system("rm /data/.flag");}if (access(FIFO_CHANNEL, 0) != 0) {int pid;pid = fork();if (pid < 0) {perror("Cannot create new child process\n");return -1;}else if (pid == 0) {create_server();exit(0);}else {sleep(1);send_to_server(size);}}else {send_to_server(size);}return 0;}

本程序适用于任何linux设备和服务器,只需要修改FIFO_CHANNEL和FIFO_CHANNEL_2的值即可。