我想你需要的可能是这个,一个正在跑的进程,你希望它暂停。首先你的权利要足够大,一般只有超级用户ROOT才能做到,你找到进程的PID后(使用ps -le)后,使用kill -STOP 进程PID 即可,改进程就会暂停(进入睡眠态,不是挂起态),这是通过信号把一个进程暂停,想恢复就是用kill -CONT 进程PID即可。因为程序是可以从载信号处理程序的,不过放心 *** 作系统不允许从在STOP和KILL这2个信号,所以暂停没问题,但能不能继续CONT,那就看进程自己有没有从载了(一般不会)。
第2个,这个程序代码是你写的,你有该程序源代码,那就很简单了,使用sleep系统调用就能进入睡眠态,还有很多其它系统调用,进入挂起,貌似没有办法,不过你请求外设,只要该外设没有响应他就会挂起,例如代码是C写的,你只要getchar(),然后你不按键盘,它就会挂起下去。
在linux中prctl可以满足这个要求,下满是man手册:PR_SET_NAME (since Linux 2.6.9)
Set the process name for the calling process, using the value in
the location pointed to by (char *) arg2. The name can be up to
16 bytes long, and should be null terminated if it contains
fewer bytes.
但是prctl修改的进程名,只能是16个字节(包括'\0')。下面是修改的代码(changetitle.c):
#include <stdio.h>
#include <sys/prctl.h>
int main(int argc, char *argv[], char *envp[])
{
char *new_name = "abcdefghijklmnopqrstuvwxyz"
getchar()
prctl(PR_SET_NAME, new_name)
getchar()
return 0
}
当新名称长度大于16时就会截断,上面的新名字截断后是abcdefghijklmno。这对于我们来说是有缺陷的。而且通过ps -aux 查看,进程名称并没有改变,改变的只是/prco/$(PID)/stat和
/prco/$(PID)/status的值,而/prco/$(PID)/cmdline并没有改变。这种方式使用起来也是不方便的。
下面介绍另一种方式,可以与上面的方式互补。
首先看一下main函数的原型:int main(int argc, char *argv[])
argv[0]存放的是终端执行的程序名称也就是进程名。argv[1...argc-1]存放的是命令行参数。
linux中main()还有一个隐藏参数就是环境变量信息,存放了运行时所需要的环境变量。
我们可以通过以下来访问这个变量
extern char **environ
argv与environ是连续存放在栈区的。下面代码可以查看参数信息:
#include <stdio.h>
#include <string.h>
extern char **environ
int main(int argc , char *argv[])
{
int i
printf("argc:%d\n" , argc)
for (i = 0i <argc++i)
{
printf("argv[%d](0x%x):%s\n" , i , (unsigned int)argv[i], argv[i])
}
printf("evriron=0x%x\n" , (unsigned int)environ[0])
return 0
}
通过上面可以看出,我们只需要修改argv[0]所指向的内存空间的内容,就可以修改进程名。但是如果新名称比argv[0]的长度小,我们可以直接修改,并把多余的部分请0,如果新名称
比argv[0]长我们需要两步:
1、申请新内存保存环境变量信息和argv[1...argc-1]参数信息
2、修改argv[0],将新名称往后到environ的最后一项清0
以下是参考代码:
#include <unistd.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <sys/prctl.h>
# define MAXLINE 2048
extern char **environ
static char **g_main_Argv = NULL/* pointer to argument vector */
static char *g_main_LastArgv = NULL/* end of argv */
void setproctitle_init(int argc, char **argv, char **envp)
{
int i
for (i = 0envp[i] != NULLi++) // calc envp num
continue
environ = (char **) malloc(sizeof (char *) * (i + 1))// malloc envp pointer
for (i = 0envp[i] != NULLi++)
{
environ[i] = malloc(sizeof(char) * strlen(envp[i]))
strcpy(environ[i], envp[i])
}
environ[i] = NULL
g_main_Argv = argv
if (i >0)
g_main_LastArgv = envp[i - 1] + strlen(envp[i - 1])
else
g_main_LastArgv = argv[argc - 1] + strlen(argv[argc - 1])
}
void setproctitle(const char *fmt, ...)
{
char *p
int i
char buf[MAXLINE]
extern char **g_main_Argv
将一个进程置于休眠状态,一般步骤如下:0. 定义并初始化(如果还没有的话)一个等待队列头(wait_queue_head_t),这个等待队列头应该是能被要休眠的进程和负责唤醒的进程都能访问 到。
1. 对进程的每次休眠,定义并初始化一个等待队列(wait_queue_t)
2. 把等待队列加入到相应的等待队列头中。
3. 把进程状态置为 TASK_INTERRUPTIBLE 或 TASK_UNINTERRUPTIBLE
4. 再次检查休眠条件是否为真,否则跳过第5步
5. 执行 schedule()
6. 清理:将进程状态改为 TASK_RUNNING(通常已经是,除非是从第4步跳过来的),把等待队列从等待队列头中删除(防止多次唤醒)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)