编写一个程序,完成后再次启动。
同时运行的程序实例不应超过一个。甚至没有丝毫时间。
您可以忽略周期中用户手动启动的任何实例。但是您的代码不应在重新启动周期中执行此操作。
程序可以在任何时间后启动,只要可以保证再次启动即可。
停止周期的唯一方法是终止进程。
您的解决方案不应该涉及重新启动环境(运行程序的环境,包括操作系统,计算机,VM,shell等)。只允许您的程序重新启动。
shutdown -r -t 0 -f
”。
编写一个程序,完成后再次启动。
同时运行的程序实例不应超过一个。甚至没有丝毫时间。
您可以忽略周期中用户手动启动的任何实例。但是您的代码不应在重新启动周期中执行此操作。
程序可以在任何时间后启动,只要可以保证再次启动即可。
停止周期的唯一方法是终止进程。
您的解决方案不应该涉及重新启动环境(运行程序的环境,包括操作系统,计算机,VM,shell等)。只允许您的程序重新启动。
shutdown -r -t 0 -f
”。
Answers:
$0&
只需将自己的新实例放在后台(新过程),然后退出即可。新实例可能会保留在调度程序运行队列中,直到完成前一个实例为止。
kill
,因为PID不断变化。临时重命名脚本文件可能是打破周期的最简单方法。假设使用单核系统。当然,对于现代裸机硬件上的Linux,这是不现实的,但是在VM中运行时很容易配置。使用可能可以实现类似的技巧taskset
,但这将减少3-char解决方案的影响。
这个答案在应用“运行”的特定含义时稍微改变了规则。有时会执行新过程fork()
,而旧过程仍然存在-即可能有可能观察到多个PID。但是,新进程将放置在Linux调度程序运行队列中,以等待CPU周期,而现有进程将继续执行。在这一点上,现有流程需要做的全部工作就是bash
自己exit()
。这确实需要花费有限的时间,尽管我相当有信心,它将在当前的时间片/调度程序量子完成之前完成。支持的事实是bash
我的虚拟机在2毫秒内启动和关闭的事实:
$ time bash -c: 真实0m0.002s 用户0m0.000s sys 0m0.000s $
在strace
输出中可以看到进一步的支持证据,表明新流程直到之前的流程完成才真正运行。
strace -f -tt -o forever.strace bash -c ./forever.sh
在输出中,我们看到原始进程的PID为6929。我们可以看到fork()
调用(实际上是clone()
),该调用返回一个新的PID为6930。这时有2个PID,但当前仅运行6929:
6929 12:11:01.031398 clone(child_stack = 0,flags = CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD,child_tidptr = 0x7f2f83ac49d0)= 6930 6929 12:11:01.031484 rt_sigprocmask(SIG_SETMASK,[],NULL,8)= 0 6929 12:11:01.031531 rt_sigprocmask(SIG_BLOCK,[CHLD],[],8)= 0 6929 12:11:01.031577 rt_sigprocmask(SIG_BLOCK,[CHLD],[CHLD],8)= 0 6929 12:11:01.031608 rt_sigprocmask(SIG_SETMASK,[CHLD],NULL,8)= 0 6929 12:11:01.031636 rt_sigprocmask(SIG_BLOCK,[CHLD],[CHLD],8)= 0 6929 12:11:01.031665 rt_sigprocmask(SIG_SETMASK,[CHLD],NULL,8)= 0 6929 12:11:01.031692 rt_sigprocmask(SIG_BLOCK,[CHLD],[CHLD],8)= 0 6929 12:11:01.031726 rt_sigprocmask(SIG_SETMASK,[CHLD],NULL,8)= 0 6929 12:11:01.031757 rt_sigprocmask(SIG_SETMASK,[],NULL,8)= 0 6929 12:11:01.031803 rt_sigprocmask(SIG_BLOCK,NULL,[],8)= 0 6929 12:11:01.031841 read(255,“”,4)= 0 6929 12:11:01.031907 exit_group(0)=? 6930 12:11:01.032016 close(255)= 0 6930 12:11:01.032052 rt_sigprocmask(SIG_SETMASK,[],NULL,8)= 0
我们可以看到6930在6929完成之前不会发出任何系统调用。可以合理地假设,这意味着6930直到6929完成才完全运行。该perf
实用程序将是证明这一点的最终方法。
top
)不是在此处使用的正确工具。但是我看到time bash -c :
在我的Ubuntu VM上仅花费2毫秒,因此我认为bash
在完成调度时间之前不要期望完成其关闭是不合理的。
它发送头,然后停止。3秒后,页面将重新加载。
文件a.php
header("Refresh: 3; url=a.php");
可以通过在发送标头之前终止页面的执行,或仅通过终止浏览器来停止此操作。
让我们考虑两个文件这两个不同的程序。这两个文件位于同一文件夹中。
文件a.php
header("Location:b.php");
文件b.php
header("Location:a.php");
在发送标头之前终止其中一个页面会终止程序(也将终止浏览器的工作)。
这是相同的程序
文件a.aspx
Response.Redirect("b.aspx")
文件b.aspx
Response.Redirect("a.aspx")
exec "$0"
exec
替换外壳而不创建新进程。这样可以确保没有第二个实例。
~/.bash_profile
!
$0
是-bash
when .bash_profile
的来源,因此只会导致语法错误。
exec ${0##-}
在~/.bash_profile
工作中:-)
C ++。COM编程的噩梦。满足所有挑战要求。
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <taskschd.h>
#include <comutil.h>
#pragma comment(lib, "taskschd.lib")
#pragma comment(lib, "comsuppw.lib")
static void timeplus (int seconds, char timestr[30]);
int main () {
CoInitializeEx(NULL, COINIT_MULTITHREADED);
CoInitializeSecurity(NULL, -1, NULL, NULL,
RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);
const char *name = "Restarter";
char path[MAX_PATH + 1];
GetModuleFileNameA(NULL, path, sizeof(path));
path[sizeof(path) - 1] = 0; // workaround for xp
ITaskService *taskman;
CoCreateInstance(CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER,
IID_ITaskService, (void **)&taskman);
taskman->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
ITaskFolder *root;
taskman->GetFolder(_bstr_t("\\"), &root);
// Delete the task.
root->DeleteTask(_bstr_t(name), 0);
// pause for 5 seconds to give user a chance to kill the cycle
fprintf(stderr, "If you want to kill the program, close this window now.\n");
Sleep(5000);
fprintf(stderr, "Sorry, time's up, maybe next time.\n");
// Create the task for 5 seconds from now.
ITaskDefinition *task;
taskman->NewTask(0, &task);
IPrincipal *principal;
task->get_Principal(&principal);
principal->put_LogonType(TASK_LOGON_INTERACTIVE_TOKEN);
ITaskSettings *settings;
task->get_Settings(&settings);
settings->put_StartWhenAvailable(VARIANT_TRUE);
settings->put_DisallowStartIfOnBatteries(VARIANT_FALSE);
settings->put_StopIfGoingOnBatteries(VARIANT_FALSE);
ITriggerCollection *triggers;
task->get_Triggers(&triggers);
ITrigger *trigger;
triggers->Create(TASK_TRIGGER_TIME, &trigger);
char when[30];
ITimeTrigger *trigger_time;
trigger->QueryInterface(IID_ITimeTrigger, (void **)&trigger_time);
trigger_time->put_Id(_bstr_t("TimeTrigger"));
timeplus(10, when);
trigger_time->put_StartBoundary(_bstr_t(when));
timeplus(300, when);
trigger_time->put_EndBoundary(_bstr_t(when));
IActionCollection *actions;
task->get_Actions(&actions);
IAction *action;
actions->Create(TASK_ACTION_EXEC, &action);
IExecAction *action_exec;
action->QueryInterface(IID_IExecAction, (void **)&action_exec);
action_exec->put_Path(_bstr_t(path));
IRegisteredTask *regtask;
root->RegisterTaskDefinition(_bstr_t(name), task,
TASK_CREATE_OR_UPDATE, _variant_t(), _variant_t(),
TASK_LOGON_INTERACTIVE_TOKEN, _variant_t(""),
®task);
regtask->Release();
action_exec->Release();
actions->Release();
trigger_time->Release();
trigger->Release();
triggers->Release();
settings->Release();
principal->Release();
task->Release();
root->Release();
taskman->Release();
CoUninitialize();
}
// outputs current utc time + given number of seconds as
// a string of the form YYYY-MM-DDTHH:MM:SSZ
static void timeplus (int seconds, char timestr[30]) {
SYSTEMTIME when;
FILETIME whenf;
LARGE_INTEGER tempval;
GetSystemTimeAsFileTime(&whenf);
tempval.HighPart = whenf.dwHighDateTime;
tempval.LowPart = whenf.dwLowDateTime;
tempval.QuadPart += seconds * 10000000LL; // 100 nanosecond units
whenf.dwHighDateTime = tempval.HighPart;
whenf.dwLowDateTime = tempval.LowPart;
FileTimeToSystemTime(&whenf, &when);
sprintf(timestr, "%04hu-%02hu-%02huT%02hu:%02hu:%02huZ",
when.wYear, when.wMonth, when.wDay,
when.wHour, when.wMinute, when.wSecond);
}
使用MSVC(或MinGW GCC,如果您具有所有依赖项)进行编译。
程序将启动并在Windows任务计划程序中注册一个一次性任务,以在5秒后启动自身(控制面板->管理工具->任务计划程序以查看,任务名为“ Restarter”)。程序将暂停5秒钟,以便您有机会在创建任务之前将其杀死。
挑战要求:
完成后再次启动自身。 是。任务排定在程序退出之前。
同一时间运行的程序不得超过一个实例。 是。程序完全退出,并且没有运行5秒钟。它由调度程序启动。
您可以忽略周期中用户手动启动的任何实例。 是的,作为使用恒定任务名称的副作用。
只要保证它再次启动即可。 是的,前提是Task Scheduler正在运行(它是标准Windows配置)。
停止周期的唯一方法是终止进程。 是的,该进程可以在运行的5秒钟窗口中终止。程序会在5秒延迟之前删除任务,此时将其杀死不会在计划程序中留下杂散任务。
您的解决方案不应涉及重新启动环境 。是。
顺便说一句,如果有人想知道为什么Windows应用程序曾经如此不稳定(在.NET和C#出现之前),这就是原因之一。如果程序员甚至一点点懒惰(上面的代码都是非常懒惰的),那么所需的错误处理量(包括我在内),资源管理和冗长性都会造成非常容易出错的情况。
bbcbasic.co.uk上的仿真器
这有点不同。它会打印歌曲“ Run”的一首诗,并播放和弦的琶音,以便您可以唱歌。它受到以下事实的启发:要执行的命令(以及程序的最后一行)当然是RUN。
所有变量都在程序开始时清除,因此需要使用上一次迭代留下的屏幕颜色来决定接下来要打印的经文。
5 C=POINT(0,0) MOD 4
10 COLOUR 129+C
15 CLS
20 RESTORE 110+C
25 READ A$
30 PRINT A$
35 FORK = 1 TO 4
40 RESTORE K+100
45 READ P
50 FORM= 1 TO 8
55 SOUND 1,-15,P,7
60 SOUND 1,-15,P-20,7
65 NEXT
70 NEXT
101 DATA 100
102 DATA 128
103 DATA 136
104 DATA 120
110 DATA Light up light up - As if you have a choice - Even if you can not hear my voice - I'll be right beside you dear.
111 DATA Louder louder - And we'll run for our lives - I can hardly speak - I understand - Why you can't raise your voice to say.
112 DATA Slower Slower - We dont have time for that - All I want is to find an easier way - To get out of our little heads.
113 DATA Have heart my dear - We're bound to be afraid - Even if its just for a few days - Makin' up for all of this mess.
120 RUN
输出(4个不同屏幕截图的剪辑)
<form /><script>document.forms[0].submit()</script>
该代码将触发正在运行的页面的破坏,然后在浏览器重新加载页面时重新创建其自身的另一个实例。
AFAIK,唯一的出路就是取消正在页面运行的标签页。
编辑:根据普遍要求,有效的HTML5代码:
<!doctype html><meta charset=utf-8><title> </title><form></form>
<script>document.forms[0].submit()</script>
该程序就像很多恶意软件一样。在关闭之前,它会在/ tmp目录中创建一个shell脚本。它分叉启动shell脚本,该脚本允许原始程序关闭并取消原始PID。短时间(2秒)后,shell脚本将使用该程序启动新进程。为简便起见,程序位置硬接线为“ / tmp / neverend /”。
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
void rebirth(){
char t[] = "/tmp/pawnXXXXXX";
char* pawnfile = mktemp(t);
if(pawnfile){
int fd = open(pawnfile, O_RDWR|O_CREAT);
const char msg[]="sleep 2\n/tmp/neverend\n";
if(fd>0){
int n = write(fd, msg, sizeof(msg));
close(fd);
pid_t pid = fork();
if(pid==0){
char* args[3] = {"bash", pawnfile, NULL};
execvp(args[0], args);
}
}
}
}
int main(int argc, char* argv[]){
printf("Starting %s\n", argv[0]);
atexit(rebirth);
printf("Exiting %s\n", argv[0]);
}
一次只运行一个“ everever”进程。每个新进程都会获得一个新的PID。最简单的方法是删除可执行文件。如果要使其更具恶性,可以同时复制可执行文件和脚本,以确保磁盘上的程序随时都有多个副本。
system()
如果规则不将fork + exec /bin/sh
视为补充程序,则可以使用。
1L.:R.
标记为:
1 LIST : RUN
在内部,它清除内部结构,从本质上清除程序,然后从清单中再次运行它。
这从根本上不同于:
1L.:G.1
标记为:
1 LIST : GOTO 1
这是一个基本的无限循环。运行它们时,您会看到速度的差异(首先是速度较慢)。
Return
?键盘缓冲区有多大?在VIC-20和C64上,它是10个字节。一个执行足够戳操作以加载键盘缓冲区的程序可能无法容纳在键盘缓冲区中,但是我编写了一些程序,该程序可以通过将更改打印到屏幕上来进行修改RUN
,然后Return
按键,并填充一些击键。这些东西在64位上特别有用,因为它没有IN
Atari用来将行合并到程序中的[IIRC] 命令。
在运行z / OS的IBM Mainframe上,运行一个实用程序,该实用程序将一个数据集(文件)复制到另一个数据集(文件)。输入是已提交以使其运行的JCL(作业控制语言)的源。输出是内部读取器(INTRDR)。您还需要确保您的系统不允许运行多个相同的作业名。使用仅具有一个启动器(作业可以在其中批量运行的地方)的作业类很好。
(在z / OS中)不涉及PID,因此挑战集失败。
您通过排干和/或冲洗来中止过程。如果出了问题,则要排干和/或冲洗,发誓,踢人,尝试热启动,最后通过冷启动或按“大红色按钮”(并射击程序员)。
一路上我可能有些夸张,但不要在工作中尝试此方法...
使用SORT的示例。JOB卡上的详细信息取决于站点。网站政策可能会禁止或禁止使用INTRDR。使用INTRDR可能需要特定的类。如果您的网站政策禁止其使用,则除非您想将自己的物品带到纸板箱中散步,否则请不要使用它。
尽管INTRDR有很好的用途,但请勿将其用于此目的。您甚至没有机会拿到盒子。
//jobname JOB rest is to your site standards
//*
//STEP0100 EXEC PGM=SORT
//SYSOUT DD SYSOUT=*
//SORTOUT DD SYSOUT=(,INTRDR) minimum required, site may require more
//SYSIN DD *
OPTION COPY
//SORTIN DD DISP=SHR,DSN=YOUR.LIBRARY.WITHJOB(JOBMEMBR)
其他实用程序也可用。快速程序也很容易做到,只需读取文件,写入文件即可。
如果您想要此错误示例,请尝试:http : //ibmmainframes.com/viewtopic.php?p=282414#282414
ugoren在其评论中暗示,复制数据集的传统方法是使用IBM实用程序IEBGENER。
但是,这些天来,许多站点都将IEBGENER别名为ICEGENER。如果可能的话,ICEGENER将使用IBM的DFSORT(或其竞争对手SyncSort)进行复制,因为SORT产品比IEBGENER在IO方面的优化程度更高。
我只是通过使用SORT剔除中间人。
如果您在IBM Mainframe站点工作,则知道应该使用的JOB卡的格式。最小的JOB卡是我所显示的,没有评论。注释将很重要,因为例如您可能应该提供会计信息。作业名称可能具有特定于站点的格式。
一些站点禁止或禁止使用INTRDR。意识到。
一些站点允许多个具有相同名称的作业同时运行。意识到。
尽管除非您是系统程序员,否则您无法设置这样的类,但是您应该寻找仅允许一个启动器的类。这样,该过程是相当安全的-但要绝对确定该类是否按所述方式工作。测试。没有这份工作。
如果您是系统程序员,那么您除了在职权范围内不会做任何事情。纳夫说。
如果一个作业同时具有相同的名称,并且有一个启动程序,则这将是恒定的作业启动/完成流,下一个作业启动/完成-直到您用以下命令的输出填充假脱机(另一个不好的事情)数千个工作(或工作编号用完)。观看JES控制台以获取警告消息。
基本上,不要这样做。如果要这样做,请不要在生产机器上进行。
稍加整理,我将考虑另一个答案,以了解如何在另一个IBM Mainframe操作系统z / VSE上执行此操作。z / VSE使用JCL。z / OS使用JCL。它们不一样 :-)
IEBGENER
那时我们只是简单地复制。
import os
os.system('kill -9 %s && python %s' % (os.getpid(), __file__))
我猜可能会变小。首先,通过对文件名进行硬编码(而不是使用__file__
)。但是在这里,无论其名称是什么,您都可以将此代码放在文件中并运行它:)
&&
为&
。
Windows批处理脚本。满足所有挑战要求。
据我所知,这是迄今为止唯一满足所有要求并且没有非标准依赖性的Windows解决方案(我的其他解决方案是类似的,但需要编译)。
@ECHO OFF
SETLOCAL
schtasks /Delete /TN RestarterCL /F
ECHO Close this window now to stop.
TIMEOUT /T 5
FOR /f "tokens=1-2 delims=: " %%a IN ("%TIME%") DO SET /A now=%%a*60+%%b
SET /A start=%now%+1
SET /A starth=100+(%start%/60)%%24
SET /A startm=100+%start%%%60
SET /A end=%now%+3
SET /A endh=100+(%end%/60)%%24
SET /A endm=100+%end%%%60
schtasks /Create /SC ONCE /TN RestarterCL /RI 1 /ST %starth:~1,2%:%startm:~1,2% /ET %endh:~1,2%:%endm:~1,2% /IT /Z /F /TR "%~dpnx0"
ENDLOCAL
程序的行为类似于我的C ++ / COM回答。
程序将启动并在Windows任务计划程序中注册一次任务,以在60秒后启动自身(控制面板->管理工具->任务计划程序以查看,任务名为“ Restarter”)。程序将暂停5秒钟,以便您有机会在创建任务之前将其杀死。
利用命令行Task Scheduler界面schtasks.exe
。脚本中的算法是在保持时间有效的同时以HH:MM格式计算时间偏移。
挑战要求:
完成后再次启动自身。 是。任务排定在程序退出之前。
同一时间运行的程序不得超过一个实例。 是。程序完全退出,并且无法运行约60秒。它由调度程序启动。
您可以忽略周期中用户手动启动的任何实例。 是的,作为使用恒定任务名称的副作用。
只要保证它再次启动即可。 是的,只要Task Scheduler正在运行并且schtasks.exe存在(在默认Windows配置中均为true)。
停止周期的唯一方法是终止进程。 是的,该进程可以在运行的5秒钟窗口中终止。程序会在5秒延迟之前删除任务,此时将其杀死不会在计划程序中留下杂散任务。
您的解决方案不应涉及重新启动环境 。是。
注意:由于命令行界面受限制,必须以分钟为单位指定重新启动时间,并且在未插入AC适配器的情况下,笔记本电脑上的任务将无法重新启动(对不起)。
我还没有看到许多依靠不相关程序重新启动它的解决方案。但这正是该at(1)
实用程序的用途:
echo "/bin/sh $0"|at now + 1 minute
实际上很难捕获正在运行的程序,因为它每分钟仅运行一次,并且退出速度如此之快。幸运的是,该atq(1)
实用程序将向您显示它仍在继续:
$ atq
493 Fri Feb 21 18:08:00 2014 a breadbox
$ sleep 60
$ atq
494 Fri Feb 21 18:09:00 2014 a breadbox
并且atrm(1)
可以让您打破循环:
$ atq
495 Fri Feb 21 18:10:00 2014 a breadbox
$ atrm 495
$ atq
您可以1 minute
用1 hour
或替换1 week
。或者让它1461 days
拥有一个每4年运行一次的程序。
电源外壳
我正在滥用(并可能违反)自己的规则。
[System.Threading.Thread]::Sleep(-1)
重新启动本身需要无限的时间。
可以通过杀死宿主进程来杀死它。
只是等着看;)
while true; do sleep 1; done
碎裂了,不是吗?
Sub Main:Shell "cmd ping 1.1.1.1 -n 1 -w 500>nul&&"""&App.Path &"\"&App.EXEName& """":End Sub
要运行,请创建一个新项目,添加带有此代码的模块,将启动对象设置为“ Sub Main”,进行编译,然后运行可执行文件。
Sub Main()
Call Shell("cmd ping 1.1.1.1 -n 1 -w 3000 > nul && """ & App.Path & "\" & App.EXEName & """")
End Sub
HTML / JAVASCRIPT
HTML文件a.html
<script>window.location = "a.html"</script>
比必须的更长,但是我很累,不在乎:)
while true; do sleep 1; done; bash $0;
您说它必须在完成后重新启动,而您并没有明确说它必须重复执行或无限期地重新启动。另外,您说过它永远不会有两个实例同时运行。;)
有很多方法可以做到这一点。我个人最喜欢的是做某事,例如在遥远的某个地方发送数据包,然后(通过许多方法)使响应触发该过程。
sleep
过程在完成时会重新启动
Android: 1秒后闹钟将重新启动活动
public class AutoRestart extends Activity
{
@Override
public void onCreate()
{
finish();
}
@Override
public void onDestroy() {
Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(
AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000,
restartServicePendingIntent);
super.onDestroy();
}
}
mpifork.c:
#include <stdio.h>
main(int argc, char * argv[])
{
srand(time(NULL));
int host = rand()%(argc-1)+1;
FILE * logFile = fopen("mpifork.log", "a");
if(logFile == NULL){
fprintf(stderr, "Error: failed to open log file\n");
} else {
fprintf(logfile, "Jumping to %s\n", argv[host]);
char * args[argc+5];
args[0] = "mpirun";
args[1] = "-H";
args[2] = argv[host];
args[3] = argv[0];
for(host = 0; host < argc-1; host++) args[host+4] = argv[host+1];
args[argc+3] = NULL;
execvp("mpirun", args);
fprintf(stderr, "exec died\n");
perror("execvp");
}
}
您必须安装OpenMPI或其他一些MPI实现。编译
mpicc -o mpifork mpifork.c
既然我考虑了一下,就没有理由不必使用mpicc-gcc或任何可以使用的编译器了。您只需要拥有mpirun。
gcc -o mpifork mpifork.c
要运行它,您可能应该包括完整的路径名,并包括主机列表。例如,我在/ etc / hosts中添加了一些都指向localhost的条目,并像这样运行它:
/home/phil/mpifork localhost localhost1 localhost2 localhost3 localhost4
可执行文件必须位于要在其上运行该文件的任何计算机上的同一目录中。
execvp
,它将不再在第一台机器上执行。
如果您想作恶,可以通过在中的命令行中包含主机的完整列表,在每台计算机上启动此命令args
。这样一遍又一遍,就可以在每台机器上重新生成其自身的副本-集群前炸弹。
但是,以这种形式,我很确定这可以满足规则。
由于它不会产生新的流程,因此不能完全确定这是否符合您的条件,但是无论如何都可以。
该程序将显示一个消息框,分配一些内存,将其自己的代码段复制到分配的内存中,然后跳转到该位置开始循环。它应该一直运行到malloc失败为止。
format PE GUI 4.0
entry a
include 'include/win32a.inc'
section '.text' code readable executable
a:
push 0
push _caption
push _message
push 0
call [MessageBoxA]
push b-a
call [malloc]
push b-a
push a
push eax
call [memcpy]
call eax
b:
section '.data' data readable writeable
_caption db 'Code challenge',0
_message db 'Hello World!',0
section '.idata' import data readable writeable
library user,'USER32.DLL',\
msvcrt,'msvcrt.dll'
import user,\
MessageBoxA,'MessageBoxA'
import msvcrt,\
malloc,'malloc',\
memcpy,'memcpy'
编译成fasm。
@
,因为我很可能不会关注它)。
考虑到对问题的最严格的理解,我认为这是不可能的。从本质上讲,它要求程序在没有其他正在运行的程序的帮助下自发启动。
有一些at
和chron
基础的答案,但最严格的阅读,atd
并且anacron
是它运行的是所有的时间补充方案,所以他们可能会被取消资格。
一种相关的方法,但稍微低一点的是使用Linux的方法init
。以root身份将此.conf文件添加到/etc/init/
:
描述“永远” 从运行级别开始[2345] 在运行级别上停止[!2345] 重生 高管睡眠10
然后init
重新读取其.conf文件:
sudo telinit 5
这将启动一个sleep
过程,该过程将持续10秒钟,然后退出。 一旦检测到上一个已消失,init
它将重新生成sleep
。
当然,它仍然init
用作补充程序。您可能会说这init
是内核的逻辑扩展,并且在任何Linux中都将始终可用。
如果这是不可接受的,那么我想下一步要做的是创建一个重新生成用户空间进程的内核模块(不确定这样做有多容易)。在这里,可以说内核不是进程,因此不是程序(补充程序)。另一方面,从CPU角度来看,内核本身就是一个程序。
称它为 prgmA
:prgmA
:
只是每当你在TI-BASIC编程的线符号的开始。您输入的不是它,而是在编辑器中。
A
并使用它的值作为基本情况,您最终会发现它逐步退出市场。
exec
linux中的功能吗?