mô tả tập tin hẹn giờ HOWTO

Phát hành:

1.13

Zz000zz này thảo luận về sự hỗ trợ của Python cho bộ mô tả tệp bộ đếm thời gian linux.

Ví dụ

Ví dụ sau đây cho thấy cách sử dụng bộ mô tả tệp hẹn giờ để thực thi một hàm hai lần một giây:

Các tập lệnh # Practical thực sự nên sử dụng bộ hẹn giờ không chặn,
# we sử dụng bộ hẹn giờ chặn ở đây để đơn giản.
nhập hệ điều hành, thời gian

# Create bộ mô tả tập tin hẹn giờ
fd = os.timerfd_create(time.CLOCK_REALTIME)

# Start hẹn giờ trong 1 giây, với khoảng thời gian nửa giây
os.timerfd_settime(fd, ban đầu=1, khoảng=0,5)

thử:
    sự kiện hẹn giờ # Process bốn lần.
    cho _ trong phạm vi (4):
        # read() sẽ chặn cho đến khi hết giờ
        _ = os.read(fd, 8)
        print("Hẹn giờ đã hết hạn")
cuối cùng:
    # Remember để đóng bộ mô tả tập tin hẹn giờ!
    os.close(fd)

Để tránh mất độ chính xác do loại float gây ra, bộ mô tả tệp hẹn giờ cho phép chỉ định thời gian hết hạn và khoảng thời gian ban đầu tính bằng nano giây nguyên với các biến thể _ns của hàm.

Ví dụ này cho thấy cách epoll() có thể được sử dụng với bộ mô tả tệp hẹn giờ để đợi cho đến khi bộ mô tả tệp sẵn sàng để đọc:

nhập os, thời gian, chọn,  cắm, sys

# Create một đối tượng epoll
ep = select.epoll()

# In trong ví dụ này, hãy sử dụng địa chỉ loopback để gửi lệnh "stop" tới máy chủ.
#
#$telnet 127.0.0.1 1234
# Trying 127.0.0.1...
# Connected tới 127.0.0.1.
 tự # Escape là '^]'.
# stop
# Connection bị đóng bởi máy chủ nước ngoài.
#
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("127.0.0.1", 1234))
sock.setblocking(Sai)
sock.listen(1)
ep.register(sock, select.EPOLLIN)

 tả tập tin hẹn giờ # Create ở chế độ không chặn.
số = 3
fds = []
cho _ trong phạm vi (num):
    fd = os.timerfd_create(time.CLOCK_REALTIME, flags=os.TFD_NONBLOCK)
    fds.append(fd)
    # Register bộ mô tả tệp hẹn giờ cho các sự kiện đã đọc
    ep.register(fd, select.EPOLLIN)

# Start bộ hẹn giờ với os.timerfd_settime_ns() tính bằng nano giây.
# Timer 1 phát ra sau mỗi 0,25 giây; bộ đếm thời gian 2 cứ sau 0,5 giây; v.v.
đối với i, fd trong enumerate(fds, start=1):
    one_sec_in_nsec = 10**9
    tôi = tôi * one_sec_in_nsec
    os.timerfd_settime_ns(fd, ban đầu=i//4, interval=i//4)

thời gian chờ = 3
thử:
    kết nối = Không 
    is_active = Đúng
    trong khi is_active:
        # Wait để đồng hồ hẹn giờ hết hạn trong 3 giây.
        # epoll.poll() trả về danh sách các cặp (fd, sự kiện).
        # fd là một bộ mô tả tập tin.
        # sock và conn[=giá trị trả về của socket.accept()] là các đối tượng socket, không phải bộ mô tả tệp.
        # So sử dụng sock.fileno() và conn.fileno() để lấy bộ mô tả tệp.
        sự kiện = ep.poll(hết thời gian)

        # If có nhiều bộ mô tả tệp hẹn giờ sẵn sàng để đọc cùng một lúc,
        # epoll.poll() trả về danh sách các cặp (fd, sự kiện).
        #
        # In cài đặt ví dụ này,
        Bộ hẹn giờ #    1st kích hoạt 0,25 giây một lần trong 0,25 giây. (0,25, 0,5, 0,75, 1,0, ...)
        hẹn giờ #    2nd cứ sau 0,5 giây trong 0,5 giây. (0,5, 1,0, 1,5, 2,0, ...)
        hẹn giờ #    3rd cứ sau 0,75 giây trong 0,75 giây. (0,75, 1,5, 2,25, 3,0, ...)
        #
        #    In 0,25 giây, chỉ có đồng hồ hẹn giờ đầu tiên kích hoạt.
        #    In 0,5 giây, bộ hẹn giờ thứ nhất và bộ hẹn giờ thứ 2 kích hoạt cùng lúc.
        #    In 0,75 giây, bộ hẹn giờ thứ 1 và bộ hẹn giờ thứ 3 kích hoạt cùng lúc.
        #    In 1,5 giây, bộ hẹn giờ thứ nhất, bộ hẹn giờ thứ 2 và bộ hẹn giờ thứ 3 kích hoạt cùng lúc.
        #
        # If một bộ mô tả tập tin hẹn giờ được báo hiệu nhiều lần kể từ đó
        # the lệnh gọi os.read() cuối cùng, os.read() trả về số lượng tín hiệu
        thứ tự máy chủ # as của byte lớp.
        print(f"Sự kiện được báo hiệu={events}")
        cho fd, sự kiện trong các sự kiện:
            nếu sự kiện & select.EPOLLIN:
                nếu fd == sock.fileno():
                    # Check nếu có yêu cầu kết nối.
                    print(f"Đang chấp nhận kết nối {fd}")
                    kết nối, addr = sock.accept()
                    conn.setblocking(Sai)
                    print(f"Kết nối được chấp nhận {conn} từ {addr}")
                    ep.register(conn, select.EPOLLIN)
                elif conn  fd == conn.fileno():
                    # Check nếu có dữ liệu để đọc.
                    print(f"Đọc dữ liệu {fd}")
                    dữ liệu = conn.recv(1024)
                    nếu dữ liệu:
                        # You nên bắt ngoại lệ UnicodeDecodeError để đảm bảo an toàn.
                        cmd = data.decode()
                        nếu cmd.startswith("stop"):
                            print(f"Đang dừng máy chủ")
                            is_active = Sai
                        khác:
                            print(f"Lệnh không xác định: {cmd}")
                    khác:
                        # No thêm dữ liệu, đóng kết nối
                        print(f"Đang đóng kết nối {fd}")
                        ep.unregister(conn)
                        conn.close()
                        kết nối = Không 
                Elif fd trong fds:
                    print(f"Bộ đếm thời gian đọc {fd}")
                    count = int.from_bytes(os.read(fd, 8), byteorder=sys.byteorder)
                    print(f"Bộ đếm thời gian {fds.index(fd) + 1} đã hết hạn {count} lần")
                khác:
                    print(f"Bộ mô tả tập tin không xác định {fd}")
cuối cùng:
    cho fd trong fds:
        ep.unregister(fd)
        os.close(fd)
    ep.close()

Ví dụ này cho thấy cách select() có thể được sử dụng với bộ mô tả tệp hẹn giờ để đợi cho đến khi bộ mô tả tệp sẵn sàng để đọc:

nhập os, thời gian, chọn,  cắm, sys

# In trong ví dụ này, hãy sử dụng địa chỉ loopback để gửi lệnh "stop" đến máy chủ.
#
#$telnet 127.0.0.1 1234
# Trying 127.0.0.1...
# Connected đến 127.0.0.1.
 tự # Escape là '^]'.
# stop
# Connection bị đóng bởi chủ nhà nước ngoài.
#
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("127.0.0.1", 1234))
sock.setblocking(Sai)
sock.listen(1)

 tả tập tin hẹn giờ # Create ở chế độ không chặn.
số = 3
fds = [os.timerfd_create(time.CLOCK_REALTIME, flags=os.TFD_NONBLOCK)
       cho _ trong phạm vi(num)]
select_fds = fds + [tất]

# Start bộ hẹn giờ với os.timerfd_settime() tính bằng giây.
# Timer 1 phát ra sau mỗi 0,25 giây; bộ đếm thời gian 2 cứ sau 0,5 giây; v.v.
đối với i, fd trong enumerate(fds, start=1):
   os.timerfd_settime(fd, ban đầu=i/4, interval=i/4)

thời gian chờ = 3
thử:
    kết nối = Không 
    is_active = Đúng
    trong khi is_active:
       # Wait để đồng hồ hẹn giờ hết hạn trong 3 giây.
       # select.select() trả về danh sách các bộ mô tả tệp hoặc đối tượng.
       rfd, wfd, xfd = select.select(select_fds, select_fds, select_fds, hết thời gian chờ)
       cho fd trong rfd:
           nếu fd == vớ:
               # Check nếu có yêu cầu kết nối.
               print(f"Đang chấp nhận kết nối {fd}")
               kết nối, addr = sock.accept()
               conn.setblocking(Sai)
               print(f"Kết nối được chấp nhận {conn} từ {addr}")
               select_fds.append(conn)
           elif conn  fd == conn:
               # Check nếu có dữ liệu để đọc.
               print(f"Đọc dữ liệu {fd}")
               dữ liệu = conn.recv(1024)
               nếu dữ liệu:
                   # You nên bắt ngoại lệ UnicodeDecodeError để đảm bảo an toàn.
                   cmd = data.decode()
                   nếu cmd.startswith("stop"):
                       print(f"Đang dừng máy chủ")
                       is_active = Sai
                   khác:
                       print(f"Lệnh không xác định: {cmd}")
               khác:
                   # No thêm dữ liệu, đóng kết nối
                   print(f"Đang đóng kết nối {fd}")
                   select_fds.remove(conn)
                   conn.close()
                   kết nối = Không 
           Elif fd trong fds:
               print(f"Bộ đếm thời gian đọc {fd}")
               count = int.from_bytes(os.read(fd, 8), byteorder=sys.byteorder)
               print(f"Bộ đếm thời gian {fds.index(fd) + 1} đã hết hạn {count} lần")
           khác:
               print(f"Bộ mô tả tập tin không xác định {fd}")
cuối cùng:
    cho fd trong fds:
       os.close(fd)
    sock.close()
    tất = Không