समय के साथ समय अंतराल जमा किए बिना बहुत कम अंतराल पर सटीक रूप से यूनिक्स कमांड चलाएं


38

सवाल

मैं एक लंबी अवधि में हर सेकंड ठीक एक यूनिक्स कमांड चलाने में सक्षम होना चाहता हूं ।

मुझे एक समाधान की आवश्यकता है, जो एक निश्चित समय के बाद पीछे नहीं रहता है, क्योंकि उस समय के लिए कमांड को निष्पादन की आवश्यकता होती है। नींद , घड़ी और एक निश्चित अजगर लिपि सभी ने मुझे इस संबंध में विफल कर दिया।

माइक्रोकंट्रोलर जैसे कि http://Arduino.cc पर मैं हार्डवेयर क्लॉक के माध्यम से हस्तक्षेप करता हूं। मैं जानना चाहता हूं कि क्या एक समान समय-सटीक शेल स्क्रिप्ट समाधान है। सभी समाधान जो मुझे StackExchange.com के भीतर मिले, एक ध्यान देने योग्य समय अंतराल के परिणामस्वरूप, अगर घंटे से अधिक चलता है। विवरण नीचे देखें।

व्यावहारिक उद्देश्य / आवेदन

मैं यह परीक्षण करना चाहता हूं कि क्या मेरा नेटवर्क कनेक्शन ncहर 1 सेकंड में टाइमस्टैम्प (netcat) के माध्यम से भेज रहा है ।

प्रेषक:

precise-timestamp-generator | tee netcat-sender.txt | nc $receiver $port

रिसीवर:

nc -l -p $port > netcat-receiver.txt

पूरा होने के बाद, दो लॉग की तुलना करें:

diff netcat-sender.txt netcat-receiver.txt

अंतर अनियंत्रित टाइमस्टैम्प होगा। इससे मुझे पता चलेगा कि मेरा LAN / WAN / ISP किस समय परेशानी पैदा करता है।


समाधान सो

while [ true ]; do date "+%Y-%m-%d %H:%M:%S" ; sleep 1; done | tee timelog-sleep.txt

समय के साथ एक निश्चित ऑफसेट हो जाता है, क्योंकि लूप के भीतर कमांड को भी थोड़ा समय लगता है।

शुद्धता

cat timelog-sleep.txt

2012-07-16 00:45:16
[...]
2012-07-16 10:20:36

सेकंड बीत गया: 34520

wc -l timelog-sleep.txt

फ़ाइल में लाइनें: 34243

सटीक संक्षेप:

  • 34520-34243 = 277 समय समस्याएँ
  • 34520/34243 = 1.008 = 0.8% की छूट

समाधान REYAT PYTHON

यहां पाया गया: हर x सेकंड में हमेशा के लिए यूनिक्स कमांड दोहराएं

repeat.py 1 "date '+%Y-%m-%d %H:%M:%S'" >> timelog-repeat-py.txt

माना जाता है कि समय की कमी से बचने के लिए, लेकिन ऐसा करने में विफल रहता है।

शुद्धता

wc -l timelog-repeat-py.txt

2012-07-16 13:42:44
[...]
2012-07-16 16:45:24

सेकंड बीत गया: 10960

wc -l timelog-repeat-py.txt

फ़ाइल में लाइनें: 10859

सटीक संक्षेप:

  • 10960-10859 = 101 टाइमिंग की समस्या
  • 10960/10859 = 1.009 = 0.9% की छूट

समाधान देखो

watch -n 1 "date '+%Y-%m-%d %H:%M:%S' >> ~/Desktop/timelog-watch.txt"

शुद्धता

wc -l timelog-watch.txt
2012-07-16 11:04:08
[...]
2012-07-16 13:25:47

सेकंड समाप्त हो गया: 8499

wc -l timelog-watch.txt

फ़ाइल में लाइनें: 8366

सटीक संक्षेप:

  • 8499-8366 = 133 समय समस्या।
  • 8499/8366 = 1.016 = 1.6% की छूट।

5
आवश्यक संकल्प, सटीकता क्या है और आपको इसकी आवश्यकता क्यों है / आप इसके लिए क्या उपयोग कर रहे हैं?
जिप्पी

यदि आप niceसोते हैं तो प्रक्रिया क्या होती है?
तिल्लो विकलंड

1
क्या आपने नींद () कॉल पर देरी को कम करने के लिए वास्तविक समय निर्धारण का उपयोग किया है।
mdpc

यह मुझे बताता है कि आपका समय हमेशा मौजूदा परिचालन स्थिति से प्रभावित होता है। यदि कोई प्रोग्राम आपके द्वारा देखभाल किए जाने वाले प्रोग्राम को कैश से अनलोड किए जाने का कारण बनता है, तो आपको समय में वृद्धि मिलेगी, जब तक आप गारंटी नहीं दे सकते कि प्रोग्राम का विशिष्ट रनटाइम आपके इच्छित अंतराल से काफी कम है। मैं एक रीयलटाइम सिस्टम पर रहना चाहता हूं, जिसमें किसी अन्य व्यक्ति या किसी एकल उपयोगकर्ता मोड में लॉग इन करने के साथ काफी नीचे छीन लिया गया है। संभवतः एक बेहतर समाधान यह है कि प्रोग्राम को लूप में स्वयं करने के लिए संशोधित किया जाए, बजाय किसी अन्य प्रोग्राम से इसे लागू करने के।
सॉ

2
प्रत्येक कमांड को अपने स्वयं के धागे में लॉन्च करें, इस तरह से कोई भी IO- संबंधित ब्लॉकिंग आपके समय को नहीं गिराता है।
जोएल कॉर्नेट

जवाबों:


12

कैसे इस पर्ल स्क्रिप्ट मैं सिर्फ काम मार पड़ी है?

#!/usr/bin/perl

use strict;
use warnings;
use Time::HiRes qw/time sleep/;

sub launch {
    return if fork;
    exec @_;
    die "Couldn't exec";
}

$SIG{CHLD} = 'IGNORE';

my $interval = shift;
my $start = time();
while (1) {
    launch(@ARGV);
    $start += $interval;
    sleep $start - time();
}

उपयोग: perl timer.pl 1 date '+%Y-%m-%d %H:%M:%S'

यह एक एकल स्किप के बिना 45 मिनट से चल रहा है, और मुझे संदेह है कि यह तब तक जारी रहेगा जब तक कि) a) सिस्टम लोड इतना अधिक नहीं हो जाता कि कांटा () एक सेकंड या बी से अधिक लेता है) एक लीप सेकंड डाला जाता है।

हालाँकि, यह गारंटी नहीं दे सकता है कि कमांड कुछ सेकंड के अंतराल पर चलती है, क्योंकि कुछ ओवरहेड है, लेकिन मुझे संदेह है कि यह एक बाधा-आधारित समाधान से बहुत खराब है।

मैंने इसे लगभग एक घंटे date +%N(नैनोसेकंड्स, जीएनयू एक्सटेंशन) के साथ चलाया और इस पर कुछ आंकड़े चलाए। इसमें सबसे अधिक अंतराल 1 155 माइक्रोसेकंड था। औसत (अंकगणित माध्य) 216 ar, माध्य 219 ic, मानक विचलन 42 ics। यह 270% 95% समय से अधिक तेजी से चला। मुझे नहीं लगता कि आप इसे सी प्रोग्राम को छोड़कर हरा सकते हैं।


1
मैंने इसे 1 सेकंड के अंतराल के साथ कोई अन्य सक्रिय उपयोगकर्ता अनुप्रयोगों के साथ रात भर में चलाया, और यह 29241 सेकंड के लिए चला, बिना एक भी दूसरा छोड़ दिया! इससे मेरा उद्देश्य पूरा होगा। तो मैं इसे फिर से आज सुबह 0.1 सेकंड के अंतराल के साथ, भाग गया GNU dateसाथ +%N: और केवल 3 मिनट के बाद यह त्रुटि फेंक दिया Time::HiRes::sleep(-0.00615549): negative time not invented yet at ~/bin/repeat.pl line 23.मेरी बचाया लिपि में लाइन 23:sleep $start - time();
porg

यदि आप इसे 0.01 सेकंड या 0.001 सेकंड के अंतराल के साथ चलाते हैं, तो यह केवल कुछ सेकंड या उससे कम की बात है जब तक कि प्रोग्राम "नकारात्मक समय" त्रुटि के साथ समाप्त नहीं होता है। लेकिन मेरे उद्देश्य के लिए यह फिट बैठता है!
porg

28

POSIX ualarm()फ़ंक्शन आपको माइक्रोसेकंड परिशुद्धता के साथ समय-समय पर अपनी प्रक्रिया को इंगित करने के लिए कर्नेल को शेड्यूल करने देता है।

एक साधारण कार्यक्रम कोड़ा:

 #include<unistd.h>
 #include<signal.h>
 void tick(int sig){
     write(1, "\n", 1);
 }
 int main(){
     signal(SIGALRM, tick);
     ualarm(1000000, 1000000); //alarm in a second, and every second after that.
     for(;;)
         pause();
 }

संकलन

 gcc -O2 tick.c -o tick

फिर इसे समय-समय पर आपकी ज़रूरत के हिसाब से संलग्न करें:

./tick | while read x; do
    date "+%Y-%m-%d %H:%M:%S"
done | tee timelog-sleep.txt

क्या मुझे उसके लिए एक विशेष शेल या सी-एसडी की आवश्यकता है? मैंने इसे संकलित किया है (जिसने लापता रिटर्न पर एक छोटी सी चेतावनी दी थी) लेकिन कोई उत्पादन नहीं किया गया था।
गणित

@ साथ -std=c99, आपको लापता रिटर्न के बारे में चेतावनी नहीं मिलेगी। अन्यथा, आपको कुछ विशेष की आवश्यकता नहीं होनी चाहिए। क्या आपने एक अतिरिक्त शून्य गलत किया? strace ./tickआपको दिखाएगा कि यह एक syscall परिप्रेक्ष्य से क्या कर रहा है
डेव

मुझे मिलता है: gcc -O2 -std = c99 -o tick tick.c tick.c: इन फंक्शन 'मेन': tick.c: 10: 5: चेतावनी: फंक्शन की निहित घोषणा 'ualarm' [-Wimplicit-function-घोषणापत्र ] tick.c: फ़ंक्शन में 'tick': tick.c: 5: 10: चेतावनी: विशेषता 'warn_unused_result [घोषित-परिणाम] के साथ घोषित' लिखना 'के वापसी मूल्य को अनदेखा करना :: ऐसा लगता है कि मेरा सिस्टम (Ubuntu 12.04) करता है इसका समर्थन नहीं करते। हालाँकि कम से कम एक आदमी पेज है कि ualarm unistd.h में होना चाहिए। (gcc 4.6.3 है)
गणित

28

क्या आपने watchपैरामीटर के साथ प्रयास किया है --precise?

watch -n 1 --precise "date '+%Y-%m-%d %H:%M:%S.%N' >> ~/Desktop/timelog-watch.txt"

आदमी पृष्ठ से:

आम तौर पर, इस अंतराल को कमांड के एक रन के पूरा होने और अगले रन की शुरुआत के बीच के समय के रूप में व्याख्या की जाती है। हालाँकि, -p या --precise विकल्प के साथ, आप हर अंतराल सेकंड में कमांड चलाने के लिए घड़ी का प्रयास कर सकते हैं। Ntptime के साथ इसे आज़माएं और ध्यान दें कि भिन्नात्मक सेकंड कैसे (लगभग) समान रहते हैं, सामान्य मोड के विपरीत जहां वे लगातार बढ़ते हैं।

पैरामीटर आपके सिस्टम पर उपलब्ध नहीं हो सकता है, हालांकि।

आपको यह भी विचार करना चाहिए कि क्या होना चाहिए जब आपके कार्यक्रम का निष्पादन एक से अधिक सेकंड की आवश्यकता हो। क्या अगले निर्धारित निष्पादन को छोड़ दिया जाना चाहिए, या इसे देर से चलाया जाना चाहिए?

अद्यतन : मैंने कुछ समय के लिए स्क्रिप्ट चलाई, और यह एक भी कदम नहीं बढ़ा:

2561 lines
start: 2012-07-17 09:46:34.938805108
end:   2012-07-17 10:29:14.938547796

अपडेट करें:--precise झंडा एक डेबियन है, पैच लेकिन बल्कि सरल है: http://patch-tracker.debian.org/patch/series/view/procps/1:3.2.8-9squeeze1/watch_precision_time.patch


बिल्कुल जाने का रास्ता। काश मैं यह +10 कर पाता।
krlmlr

कौन सा संस्करण watchउस विकल्प का समर्थन करता है? यह मेरे द्वारा जाँच की गई किसी भी मशीन पर नहीं था।
tylerl

इसका संस्करण 0.3.0, जो उबंटू 12.04 पर वर्तमान संस्करण है। यह procps पैकेज के संस्करण 3.2.8-11ubuntu6 से आता है।
डेनियल कुल्मन

हम्म, प्रॉप्स सोर्स पैकेज का समर्थन नहीं करता है --precise। यह एक डेबियन जोड़ है (3.2.8-9, watch_preaches_time.patch)
डेनियल कुल्मन

1
ठीक है, लेकिन सवाल पर टिप्पणियों में mdpc के समान है: यह तब भी विफल हो सकता है जब आपका सिस्टम भारी लोड के तहत हो। मैंने इसे तनाव के साथ संयोजन में परीक्षण किया (डिस्क और कोर पर भार डालते हुए) और यह मिला: 2012-07-24 07:20:21.864818595 2012-07-24 07:20:22.467458430 2012-07-24 07:20:23.068575669 2012-07-24 07:20:23.968415439 वास्तविक समय सामान (गिरी आदि) एक कारण के लिए बाहर है!
गणित

18

crontab1 मिनट का संकल्प है। यदि आप उस समय प्रति मिनट जमा होने और फिर अगले मिनट पर रीसेट करने के साथ ठीक हैं, तो यह मूल विचार काम कर सकता है:

* * * * * for second in $(seq 0 59); do /path/to/script.sh & sleep 1s;done

ध्यान दें कि script.shपृष्ठभूमि में भी चलाया जाता है। यह लूप को कम करने में मदद करना चाहिए जो लूप के प्रत्येक पुनरावृत्ति के साथ जमा होता है।

कितना अंतराल sleepउत्पन्न होता है, इसके आधार पर , अगले मिनट के दूसरे 0 के साथ दूसरे 59 ओवरलैपिंग का मौका है।

EDIT कुछ परिणामों में टॉस करता है, प्रश्न में उसी प्रारूप में:

$ cat timelog-cron
2012-07-16 20:51:01
...
2012-07-16 22:43:00

1 घंटा 52 मिनट = 6720 सेकंड

$ wc -l timelog-cron
6720 timelog-cron

0 टाइमिंग की समस्या, 0% की छूट। किसी भी समय संचय हर मिनट रीसेट करता है।


1
क्या मैं पूछ सकता हूं कि इसे क्यों ठुकरा दिया गया?
इज़्काता

2
यह एक बदसूरत हैक है
hamamu

2
@ हाहामू इसके बारे में क्या बदसूरत है? पीसी पर सामान्य उद्देश्य ओएस बहुत सटीक समय-महत्वपूर्ण संचालन के लिए डिज़ाइन नहीं किया गया है, इसलिए आप और क्या उम्मीद कर सकते हैं? यदि आप "सुरुचिपूर्ण" और बिल्कुल सटीक समय चाहते हैं, तो आपको एक अलग सीपीयू अनुसूचक का उपयोग करना होगा, या एक वास्तविक समय कर्नेल पर स्विच करना होगा, या समर्पित हार्डवेयर का उपयोग करना होगा, आदि यह पूरी तरह से वैध समाधान है और मुझे इसका कोई कारण नहीं दिखता है downvotes। यह निश्चित रूप से उस पर एक सुधार है जो केवल "पृष्ठभूमि में चलाया गया" था, जो कि समय-समय पर क्रोन के माध्यम से पुन: सिंकिंग के बिना था।
jw013

1
साथ ही इसे रोकना आसान है। चक्र के बीच में इसे मारने का जोखिम उठाने की कोई आवश्यकता नहीं है - कॉन्टैब से प्रवेश को हटा दें और यह मिनट के अंत में अपने आप खत्म हो जाता है।
इजाकाता

आप बस भाग्यशाली हैं कि आपके सिस्टम पर cronदूसरा सटीक है, लेकिन यह सामान्य रूप से ऐसा नहीं है
दिमित्री ग्रिगोरीव

15

आपकी समस्या यह है कि आप अपने कार्यक्रम को चलाने के बिना एक निश्चित समय के लिए सो रहे हैं, जबकि पिछली बार जब आप सोए थे , उस समय की मात्रा पर विचार किए बिना ।

आप यह कर सकते हैं कि बैश या किसी अन्य प्रोग्रामिंग भाषा है, लेकिन कुंजी यह निर्धारित करने के लिए घड़ी का उपयोग करने के लिए है कि अगली नींद कितनी लंबी है। सोने से पहले, घड़ी की जांच करें, देखें कि आपके पास कितना समय बचा है, और अंतर को सोएं।

प्रक्रिया शेड्यूलिंग समझौता होने की वजह से, आपको घड़ी की टिक पर सही जागने की गारंटी नहीं है, लेकिन आपको काफी करीब होना चाहिए (कुछ एमएस अनलोड के भीतर, या कुछ सौ एमएस लोड के तहत)। और आप समय के साथ त्रुटि जमा नहीं करेंगे क्योंकि हर बार जब आप हर नींद चक्र पर फिर से सिंक्रनाइज़ कर रहे हैं और किसी भी संचित त्रुटि को दूर कर रहे हैं।

यदि आपको घड़ी की टिक को ठीक से हिट करने की आवश्यकता है, तो आप जो देख रहे हैं वह एक वास्तविक समय ऑपरेटिंग सिस्टम है , जो वास्तव में इस उद्देश्य के लिए डिज़ाइन किया गया है।


मुझे लगता है कि यह भी बहुत संभावित है कि प्रोग्राम porg ने इच्छित प्रक्रिया को चलाते समय ब्लॉक का परीक्षण किया है - जो तार्किक रूप से उन्हें उस मशीन को मारने से बचने के लिए करना चाहिए जिस पर वे चल रहे हैं।
सिम्बियन

आप ब्लॉक करते हैं या नहीं, तंत्र ठीक काम करता है। यदि आप ब्लॉक करते हैं, तो आप अवरुद्ध होने के बाद बचे समय को सोते हैं। यदि आप ब्लॉक नहीं करते हैं, तो आपका टाइमिंग थ्रेड या प्रक्रिया सो रही है जबकि दूसरा काम कर रहा है। किसी भी तरह से, एक ही परिणाम।
tylerl

@tylerl: आपके समाधान के लिए कंक्रीट कमांड लाइन कैसी दिखेगी?
porg

मुझे लगता है कि आपका मतलब @lynxlynxlynx
porg

@porg आपको date +%S.%Nउप-सेकंड परिशुद्धता के साथ सेकंड की संख्या प्राप्त करने के लिए, और usleepउप-सेकंड परिशुद्धता के साथ सोने के लिए उपयोग करने की आवश्यकता है , लेकिन उसके बाद यह सिर्फ गणित की बात है।
tylerl

7

मैं हमेशा बस कुछ अंतराल पर वास्तव में चलाने पर छोड़ दिया है। मुझे लगता है कि आपको C प्रोग्राम लिखना होगा, और अपने स्वयं के कोड के साथ 1-सेकंड के अंतराल के हिस्से को पार न करने के लिए बहुत सावधानी से ध्यान देना होगा। आपको संभवतः इसे काम करने के लिए थ्रेडिंग या कई, अंतर-संचार प्रक्रियाओं का उपयोग करना होगा। थ्रेड-स्टार्टिंग या प्रक्रिया-प्रारंभ समय ओवरहेड से बचने के लिए ध्यान रखें।

एक संदर्भ जो 1993 की प्रासंगिक तिथियों को लगता है: सीपीयू यूटिलाइज़ेशन एस्टिमेशन और कोड प्रोफाइलिंग के लिए एक रैंडमाइज़्ड सैंपलिंग क्लॉक, आप परिशिष्ट "एडवरसरी सोर्स कोड" पर एक नज़र डालना चाहेंगे कि वे सही समय अंतराल को कैसे मापते हैं, और "जाग" सिर्फ सही समय पर उनका कार्यक्रम। चूंकि कोड 19 वर्ष पुराना है, यह शायद सीधे या आसानी से पोर्ट नहीं करेगा, लेकिन यदि आप इसे पढ़ते हैं और इसे समझने की कोशिश करते हैं, तो शामिल सिद्धांत आपके कोड का मार्गदर्शन कर सकते हैं।

EDIT: एक और संदर्भ मिला है जो मदद कर सकता है: इंटरएक्टिव और सॉफ्ट रियल-टाइम प्रक्रियाओं के निर्धारण पर प्रभाव के समाधान की घड़ी जो आपको किसी भी सैद्धांतिक पृष्ठभूमि के साथ मदद करनी चाहिए।


4

Nanosleep () ( http://linux.about.com/library/cmd/blcmdl2_nanosleep.htm से ) देखें। अपने कार्यक्रम को 1 सेकंड की नींद बनाने के बजाय, इसे सोने दें (1 - इसे चलाने के लिए पर्याप्त समय) सेकंड। आपको एक बेहतर समाधान मिलेगा।


आप इसे नियमित रूप से कर सकते हैं sleep, अर्थात sleep 0.99। समस्या यह है कि इसे चलाने में जितना समय लगता है वह निरंतर से बहुत दूर है, यहां तक ​​कि इसका औसत मूल्य भी समय के साथ कम हो सकता है।
दिमित्री ग्रिगोरीव

3

अपने कमांड को बैकग्राउंड में चलाने का प्रयास करें ताकि यह लूप टाइमिंग को इतना प्रभावित न करे, लेकिन यह भी पर्याप्त नहीं होगा यदि आप लंबे समय तक कोई संचय नहीं चाहते हैं क्योंकि निश्चित रूप से कुछ मिलीसेकंड लागत इससे जुड़ी है।

तो, यह बेहतर होने की संभावना है, लेकिन यह भी संभावना है कि अभी भी पर्याप्त नहीं है:

while [ true ]; do date "+%Y-%m-%d %H:%M:%S" & sleep 1; done | 
tee timelog-sleep.txt

मेरे कंप्यूटर पर इसने 20 मिनट या 0,1 प्रति मिनट में 2 त्रुटियां दीं, जो आपके रन पर लगभग पांच गुना सुधार है।


इसके साथ समस्या sleep 1यह है कि यह कम से कम एक सेकंड सोने की गारंटी है - कभी कम नहीं। इसलिए त्रुटि जम जाती है।
हमामू

दो अलग-अलग कंप्यूटरों से समय के परिणामों की तुलना करना काफी व्यर्थ है, जब तक कि आपने अपने सिस्टम पर मूल कोड नहीं चलाया है और ओपी के समान परिणाम प्राप्त किया है।
दिमित्री ग्रिगोरीव

1

बदसूरत लेकिन यह काम करता है। यदि आपको इस तरह से लूप की आवश्यकता है, तो आपको शायद अपने कार्यक्रम के डिजाइन पर पुनर्विचार करना चाहिए। यह मूल रूप से जांचता है कि क्या वर्तमान पूरा दूसरा पिछले चेक किए गए के बराबर है और दूसरे के परिवर्तन के बाद से नैनोसेकंड की संख्या को प्रिंट करता है। सटीकता नींद से प्रभावित है ।001।

while true; do T=$( date +%s ); while [[ $T -eq $( date +%s ) ]]; do sleep .001; done; date "+%N nanoseconds late"; done

सटीकता मिलिसेकंड में है, बशर्ते कि 'पेलोड' date "+%N nanoseconds late"सिर्फ एक सेकंड से अधिक समय तक न हो। आप नींद की अवधि को बढ़ाकर सीपीयू लोड को कम कर सकते हैं या यदि आप वास्तव में बुरा नहीं मानते हैं तो नींद की कमान को बदल दें true

002112890 nanoseconds late
001847692 nanoseconds late
002273652 nanoseconds late
001317015 nanoseconds late
001650504 nanoseconds late
002180949 nanoseconds late
002338716 nanoseconds late
002064578 nanoseconds late
002160883 nanoseconds late

यह बुरा अभ्यास है क्योंकि आप मूल रूप से एक घटना के लिए आपको सीपीयू पोल बनाते हैं और आप सीपीयू चक्र बर्बाद कर रहे हैं। आप संभवत: एक टाइमर इंटरप्ट (बश से संभव नहीं) या एक माइक्रोकंट्रोलर की तरह समर्पित हार्डवेयर का उपयोग करना चाहते हैं। एक पीसी और उसके ऑपरेटिंग सिस्टम को उच्च समय सटीकता के लिए डिज़ाइन नहीं किया गया है।


1

एक अन्य विधि एक लूप में एक सस्पेंड का उपयोग करना और एक सटीक बाहरी कार्यक्रम से SIGCONT भेजना होगा। एक सिग्नल भेजना बहुत हल्का है और इसमें कुछ निष्पादित करने की तुलना में बहुत कम विलंबता होगी। आप "at" कमांड के साथ कमांड का एक गुच्छा पहले से कतार में रख सकते हैं, शायद ही कोई "पर" का उपयोग करता है, मुझे यकीन नहीं है कि यह कितना सटीक है।

यदि परिशुद्धता महत्वपूर्ण है और आप इसके बारे में गंभीर होना चाहते हैं, तो यह उस तरह के अनुप्रयोग की तरह लगता है जहां आमतौर पर आप RTOS का उपयोग करते हैं, जो कि RT-Preempt पैच कर्नेल के साथ लिनक्स के तहत किया जा सकता है, जो आपको सटीक और कुछ माप देगा इंटरप्ट कंट्रोल, लेकिन यह इसके लायक होने से ज्यादा परेशान कर सकता है।

https://rt.wiki.kernel.org/index.php/RT_PREEMPT_HOWTO

Xenomai भी सहायक हो सकती है, यह एक पूर्ण RTOS कार्यान्वयन है और इसे x86 और x86_64 के लिए पोर्ट किया गया है, लेकिन इसमें कुछ प्रोग्रामिंग शामिल है।

http://www.xenomai.org/index.php/Main_Page


1

के साथ ksh93(जिसमें एक फ्लोटिंग पॉइंट $SECONDSऔर एक बिल्डिन है sleep)

typeset -F SECONDS=0
typeset -i i=0
while true; do
   cmd
   sleep "$((++i - SECONDS))"
done

एक ही स्क्रिप्ट के साथ भी काम करेगा zshलेकिन आपके सिस्टम के sleepकमांड को इनवाइट करेगा । zshएक zselectबिलिन है, लेकिन केवल 1/100 संकल्प के साथ।


0

मैं एक छोटे सी कार्यक्रम के साथ जाऊंगा:

#include <sys/time.h>
#include <unistd.h>

int main(int argc, char **argv, char **envp)
{
    struct timeval start;
    int rc = gettimeofday(&start, NULL);
    if(rc != 0)
            return 1;

    for(;;)
    {
        struct timeval now;
        rc = gettimeofday(&now, NULL);
        useconds_t delay;
        if(now.tv_usec < start.tv_usec)
            delay = start.tv_usec - now.tv_usec;
        else
            delay = 1000000 - now.tv_usec + start.tv_usec;
        usleep(delay);
        pid_t pid = fork();
        if(pid == -1)
            return 1;
        if(pid == 0)
            _exit(execve(argv[1], &argv[1], envp));
    }
}

यह कार्यक्रम उम्मीद करता है कि यह कार्यक्रम अपने पहले तर्क के रूप में पूर्ण पथ के साथ कॉल करेगा, और किसी भी शेष तर्क से गुजरता है। यह कमांड के खत्म होने का इंतजार नहीं करेगा, इसलिए यह खुशी से कई उदाहरण शुरू करेगा।

इसके अलावा, यहां कोडिंग शैली वास्तव में मैला है, और कई मान्यताओं को बनाया गया है जो कि लागू मानकों की गारंटी हो सकती है या नहीं, अर्थात इस कोड की गुणवत्ता "मेरे लिए काम करती है" है।

एनटीपी या घड़ी को मैन्युअल रूप से सेट करके समायोजित किए जाने पर यह कार्यक्रम कुछ लंबा या छोटा अंतराल प्राप्त करेगा। यदि प्रोग्राम को इसे संभालना चाहिए, तो POSIX प्रदान करता है timer_create(CLOCK_MONOTONIC, ...)जो इससे अप्रभावित है।


0

आपको वर्तमान समय का ध्यान रखना चाहिए और इसकी शुरुआत के समय से तुलना करनी चाहिए। इसलिए आप प्रत्येक पुनरावृत्ति के समय की गणना करें, एक निश्चित राशि नहीं। इस तरह से आप समय-समय पर त्रुटियों को जमा नहीं करेंगे और जहाँ से आपको होना चाहिए वहाँ से दूर चले जाएँगे क्योंकि आप अपने समय को शुरू से निरपेक्ष समय तक प्रत्येक लूप को रीसेट करते हैं।

साथ ही कुछ नींद के कार्य जल्दी लौट आते हैं अगर कोई अंतर हो जाता है, तो इस मामले में आपको अपनी नींद की विधि को फिर से कॉल करना होगा जब तक कि पूरी मात्रा बीत नहीं जाती।


0

यहाँ एक बैश स्क्रिप्ट है और अत्यधिक सटीक है। यह माइक्रोसेकंड परिशुद्धता के लिए usleep का उपयोग करता है।

http://wiki.junkemailfilter.com/index.php/How_to_run_a_Linux_script_every_few_seconds_under_cron

वहाँ 3 स्क्रैप है। नीचे वाले को देखो। उचित सटीकता के साथ प्रति मिनट लगभग 2400 निष्पादन करेंगे। और यह वास्तव में सरल है।


0

यह एक सेकंड में कम से कम 100 बार बहुत सटीक रिज़ॉल्यूशन के साथ चल सकता है।

प्रति मिनट छोरों की संख्या की निर्देशिका का अस्तित्व अनुसूची बनाता है। यह संस्करण माइक्रोसेकंड संकल्प का समर्थन करता है, यह मानते हुए कि आपका कंप्यूटर इसे संभाल सकता है। प्रति मिनट निष्पादन की संख्या 60 से समान रूप से विभाज्य नहीं है और न ही यह 60 तक सीमित है मैंने इसे 6000 तक परीक्षण किया है और यह काम करता है।

इस संस्करण को /etc/init.d निर्देशिका में स्थापित किया जा सकता है और सेवा के रूप में चलाया जा सकता है।

#! /bin/sh

# chkconfig: 2345 91 61
# description: This program is used to run all programs in a directory in parallel every X times per minute. \
#              Think of this program as cron with microseconds resolution.

# Microsecond Cron
# Usage: cron-ms start
# Copyright 2014 by Marc Perkel
# docs at http://wiki.junkemailfilter.com/index.php/How_to_run_a_Linux_script_every_few_seconds_under_cron"
# Free to use with attribution

# The scheduling is done by creating directories with the number of"
# executions per minute as part of the directory name."

# Examples:
#   /etc/cron-ms/7      # Executes everything in that directory  7 times a minute
#   /etc/cron-ms/30     # Executes everything in that directory 30 times a minute
#   /etc/cron-ms/600    # Executes everything in that directory 10 times a second
#   /etc/cron-ms/2400   # Executes everything in that directory 40 times a second

basedir=/etc/cron-ms

case "$1" in

   start|restart|reload)
   $0 stop
   mkdir -p /var/run/cron-ms
   for dir in $basedir/* ; do
      $0 ${dir##*/} &
   done
   exit
   ;;

   stop)
   rm -Rf /var/run/cron-ms
   exit
   ;;

esac

# Loops per minute is passed on the command line

loops=$1
interval=$((60000000/$loops))

# Just a heartbeat signal that can be used with monit to verify it's alive

touch /var/run/cron-ms

# After a restart the PIDs will be different allowing old processes to terminate

touch /var/run/cron-ms/$$

# Sleeps until a specific part of a minute with microsecond resolution. 60000000 is full minute

usleep $(( $interval - 10#$(date +%S%N) / 1000 % $interval ))

# Deleting the PID files exit the program

if [ ! -f /var/run/cron-ms/$$ ]
then
   exit
fi

# Run all the programs in the directory in parallel

for program in $basedir/$loops/* ; do
   if [ -x $program ] 
   then
      $program &> /dev/null &
   fi
done

exec $0 $loops
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.