เพราะเหตุใดเวลาจึงถูกรายงานตามเวลา () บางครั้ง 1 วินาทีหลังองค์ประกอบวินาทีของ timespec_get () ในรหัส C?


12

ตัวอย่างโค้ดต่อไปนี้:

struct timespec ts;
for (int x = 0; x < 100000000; x++) {
    timespec_get(&ts, TIME_UTC);
    long cTime = (long) time(NULL);
    if (cTime != ts.tv_sec && ts.tv_nsec < 3000000) {
        printf("cTime: %ld\n", cTime);
        printf("ts.tv_sec: %ld\n", ts.tv_sec);
        printf("ts.tv_nsec: %ld\n", ts.tv_nsec);
    }
}

สร้างผลลัพธ์นี้:

...
cTime: 1579268059
ts.tv_sec: 1579268060
ts.tv_nsec: 2527419
cTime: 1579268059
ts.tv_sec: 1579268060
ts.tv_nsec: 2534036
cTime: 1579268059
ts.tv_sec: 1579268060
ts.tv_nsec: 2540359
cTime: 1579268059
ts.tv_sec: 1579268060
ts.tv_nsec: 2547039
...

ทำไมความแตกต่างระหว่างcTimeและts.tv_sec? ts.tv_nsec >= 3000000โปรดทราบว่าปัญหาไม่ได้เกิดขึ้นหากมีเงื่อนไขที่มีการเปลี่ยนแปลงไป ปัญหานี้ขึ้นอยู่กับนาโนวินาทีที่มีขนาดเล็กกว่า 3000000


คุณจะต้องมีความเฉพาะเจาะจงมากขึ้นเกี่ยวกับระบบปฏิบัติการที่ใช้เวอร์ชันของเวอร์ชันเวอร์ชันของไลบรารี C ที่ใช้
โปรแกรมเมอร์บางคนเพื่อนที่

2
@Someprogrammerdude Linux Debian 8, GCC 6.3.0
Theo d'Or

อะไรนะtimespec_get()? นี่คือ C หรือ C ++ หรือไม่ std::timespec_getดูเหมือนว่า โปรดใช้แท็กที่เหมาะสม
Marco Bonelli

@MarcoBonelli: มันถูกเพิ่มใน C ใน C11 สามารถทำซ้ำออนไลน์
ShadowRanger

@ShadowRanger ขอบคุณสำหรับการอ้างอิงฉันไม่เห็นmanรายการtimespec_getในระบบของฉันดังนั้นฉันจึงข้ามไปยังข้อสรุป มีเหตุผล.
Marco Bonelli

คำตอบ:


11

เหตุผลก็คือคุณ (โดยปริยาย) ใช้นาฬิการะบบที่แตกต่างกัน timespec_get()ใช้นาฬิกาเรียลไทม์ทั้งระบบที่มีความคมชัดสูงและtime()ใช้นาฬิกาเรียลไทม์หยาบ

ลองใช้ดู

clock_gettime(CLOCK_REALTIME_COARSE, &ts);

แทนที่จะเป็นของคุณtimespec_get()ความแตกต่างควรหายไป

แก้ไข:

สามารถดูได้ในLinux Kernel Source, vclock_gettime.c

อันที่จริงปัญหานี้ดูเล็กน้อยที่นี่ ส่วนวินาทีของสมาชิกโครงสร้างที่ใช้โดยCLOCK_REALTIME_COARSEและCLOCK_REALTIMEมีค่าเหมือนกัน แต่ส่วนnanosecondsนั้นแตกต่างกัน ด้วยCLOCK_REALTIMEอาจมีขนาดใหญ่กว่า1000000000(ซึ่งเป็นหนึ่งวินาที) ในกรณีนี้จะถูกกำหนดไว้ที่การโทร:

ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
ts->tv_nsec = ns;

การแก้ไขนี้จะดำเนินการกับค่าหรือด้วยCLOCK_REALTIME_COARSE time()นี้จะอธิบายถึงความแตกต่างระหว่างและCLOCK_REALTIMEtime()


เอกสารนี้มีที่ใดที่หนึ่งหรือเป็นเพียงสิ่งประดิษฐ์ที่timeถูกนำไปใช้กับนาฬิกาที่มีประสิทธิภาพมากขึ้น แต่น่าจะมีความแม่นยำน้อยกว่า (โดยทฤษฏีว่ามันมีเม็ดละเอียดเพียงสองเม็ดเท่านั้น ปกคลุมด้วยเวลาจริงเป็นมิลลิวินาที (การทดสอบออนไลน์แสดงความล่าช้าเป็นครั้งคราวมากกว่ามิลลิวินาที แต่ไม่มาก) เมื่อคุณขอแค่ความละเอียดที่สองไม่ใช่สิ่งสำคัญที่ฉันเดา
ShadowRanger

@ShadowRanger ฉันเพิ่มรายละเอียดเพิ่มเติม
Ctx

ไม่ใช่เอกสารแสดงเจตจำนงที่ชัดเจน แต่ก็มีรายละเอียดเพียงพอสำหรับการลงคะแนน :-) ตลกที่นาฬิกาสามารถรายงานได้มากกว่าหนึ่งวินาทีของเสี้ยววินาทีเพิ่มเติม
ShadowRanger

@ShadowRanger ฉันไม่สามารถหาเอกสารจริงอื่น ๆ นอกเหนือจากแหล่งที่มาที่ซึ่งยังหมายถึงว่าพฤติกรรมนี้ยังอาจมีการเปลี่ยนแปลงในรายละเอียดโดยไม่ต้องแจ้งให้ทราบล่วงหน้า
Ctx

@Ctx ขอบคุณสำหรับคำตอบอย่างละเอียด! ฉันจะใช้ timespec_get () แทน clock_gettime () ที่คุณแนะนำเนื่องจาก timespec_get () คือ C11 แทนที่จะเป็น POSIX และไม่ต้องการการตั้งค่าที่จะใช้นาฬิกา ฉันไม่มีความคิดที่จะใช้นาฬิกาที่แตกต่างกัน แต่ให้ทางเลือกฉันไม่เห็นจุดมากในการใช้นาฬิกาหยาบ
Theo d'Or
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.