Атрибут сокета, используемый для временной привязки программного обеспечения, SO_TIMESTAMPNS. Этот атрибут socket возвращает время от системных часов. Он не генерируется в аппаратном обеспечении, скорее это моментальный снимок системного времени, когда прерывание обрабатывается в программном обеспечении. Мы можем получить доступ к этой метке времени через вспомогательные данные (CMSG), который не является частью полезной нагрузки сокета, используя:
int level, type;
struct cmsghdr *cm;
struct timespec *ts = NULL;
for (cm = CMSG_FIRSTHDR(&msg); cm != NULL; cm = CMSG_NXTHDR(&msg, cm))
{
level = cm->cmsg_level;
type = cm->cmsg_type;
if (SOL_SOCKET == level && SO_TIMESTAMPNS == type) {
ts = (struct timespec *) CMSG_DATA(cm);
printf("SW TIMESTAMP %ld.%09ld\n", (long)ts[0].tv_sec, (long)ts[0].tv_nsec);
}
}
Опция SO_TIMESTAMPING гнездо предлагает множество различных флагов, некоторые из них,
SOF_TIMESTAMPING_TX_HARDWARE // Transmit timestamp generated in hardware by NIC clock
SOF_TIMESTAMPING_RX_HARDWARE // Receive timestamp generated in hardware by NIC clock
SOF_TIMESTAMPING_TX_SOFTWARE // Transmit timestamp generated in kernel driver by NIC clock
SOF_TIMESTAMPING_RX_SOFTWARE // Receive timestamp generated in kernel driver by NIC clock
Эта опция сокета не поддерживается всеми сетевыми интерфейсами (NIC). В настоящее время многие сетевые сетевые адаптеры поддерживают SO_TIMESTAMPING. Для того, чтобы найти, если конкретный драйвер поддерживает интерфейс SO_TIMESTAMPING, использование:
ethtool -T ethX // where X corresponds to your particular interface
Это будет возвращать все атрибуты сокета ethX поддерживает для временных меток.
Чтобы использовать аппаратные функции меток времени, предоставляемый определенным сетевым адаптером, используйте код:
int flags;
flags = SOF_TIMESTAMPING_TX_HARDWARE
| SOF_TIMESTAMPING_RX_HARDWARE
| SOF_TIMESTAMPING_TX_SOFTWARE
| SOF_TIMESTAMPING_RX_SOFTWARE
| SOF_TIMESTAMPING_RAW_HARDWARE;
if (setsockopt(sd, SOL_SOCKET, SO_TIMESTAMPING, &flags, sizeof(flags)) < 0)
printf("ERROR: setsockopt SO_TIMESTAMPING\n");
int level, type;
struct cmsghdr *cm;
struct timespec *ts = NULL;
for (cm = CMSG_FIRSTHDR(&msg); cm != NULL; cm = CMSG_NXTHDR(&msg, cm))
{
if (SOL_SOCKET == level && SO_TIMESTAMPING == type) {
ts = (struct timespec *) CMSG_DATA(cm);
printf("HW TIMESTAMP %ld.%09ld\n", (long)ts[2].tv_sec, (long)ts[2].tv_nsec);
}
}
оборудование, если поддерживается, другое ядро. Обычно такое аппаратное обеспечение будет использовать что-то вроде PTP, чтобы синхронизировать карту, поэтому вы должны получать временную метку по отношению к часам (не уверен, что она гарантирована как монотонная, хотя, может быть, кто-то может прокомментировать ..) – Nim
@Nim, который один возвращает оборудование, если поддерживается? SO_TIMESTAMPNS? Должен ли я включать аппаратную метку времени? – Maverik
Обычно аппаратные средства, поддерживающие эту функциональность, будут видеть опцию сокета ('SO_TIMESTAMPNS' или' SO_TIMESTAMP'), а затем будут штамповать пакеты. Так, например, если у вас есть соответствующая карта солнечной вспышки, то настройка параметров приведет к тому, что карта будет отмечена меткой времени. Иначе это будет управлять ядром. Честно говоря, мне действительно не нравится, что вы должны прочитать заголовки элементов управления, чтобы на самом деле получить временную метку, хотя это ужасный интерфейс. – Nim