select、poll、epoll
select、poll、epoll
select
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
- int nfds:被select管理的文件描述符的个数,最大描述符编号+1
- fd_set *readfds:读文件描述符集合
- fd_set *writefds:写文件描述符集合
- fd_set *exceptfds:异常文件描述符集合
- struct timeval *timeout:超时时间,NULL:永远等待,正数:时间长度,0:立即返回
使用结构体表示,不存在负数值的情况,所以用NULL,正数,0 表示三种超时状态
总结:fd_set为一个1024比特的位图,位图中每一位代表一个文件描述符。
void FD_CLR(int fd, fd_set *set);
从set中清除fd
int FD_ISSET(int fd, fd_set *set);
查看fd是否存在与set中
void FD_SET(int fd, fd_set *set);
将fd加入set
void FD_ZERO(fd_set *set);
将set清空
在产生select调用时,文件描述符位图需从用户态拷贝到内核态。内核态处理完fd事件后再拷贝给用户态。之后用户态判定哪些文件描述符处于就绪状态,从而处理。用户态代码需要遍历所有的文件描述符。select处理文件描述符的上限为1024。若需要扩充文件描述符上限,则需要通过重新编译内核源码实现。
man select
SELECT(2) Linux Programmer's Manual SELECT(2)NAMEselect, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - synchronous I/O multiplexingSYNOPSIS#include <sys/select.h>int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);void FD_CLR(int fd, fd_set *set);int FD_ISSET(int fd, fd_set *set);void FD_SET(int fd, fd_set *set);void FD_ZERO(fd_set *set);int pselect(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, const struct timespec *timeout,const sigset_t *sigmask);Feature Test Macro Requirements for glibc (see feature_test_macros(7)):pselect(): _POSIX_C_SOURCE >= 200112LDESCRIPTIONselect() allows a program to monitor multiple file descriptors, waiting until one or more of the file descriptors become "ready" for some class of I/Ooperation (e.g., input possible). A file descriptor is considered ready if it is possible to perform a corresponding I/O operation (e.g., read(2), ora sufficiently small write(2)) without blocking.select() can monitor only file descriptors numbers that are less than FD_SETSIZE; poll(2) and epoll(7) do not have this limitation. See BUGS.File descriptor setsThe principal arguments of select() are three "sets" of file descriptors (declared with the type fd_set), which allow the caller to wait for threeclasses of events on the specified set of file descriptors. Each of the fd_set arguments may be specified as NULL if no file descriptors are to bewatched for the corresponding class of events.Note well: Upon return, each of the file descriptor sets is modified in place to indicate which file descriptors are currently "ready". Thus, if usingselect() within a loop, the sets must be reinitialized before each call. The implementation of the fd_set arguments as value-result arguments is a de‐sign error that is avoided in poll(2) and epoll(7).The contents of a file descriptor set can be manipulated using the following macros:FD_ZERO()This macro clears (removes all file descriptors from) set. It should be employed as the first step in initializing a file descriptor set.FD_SET()This macro adds the file descriptor fd to set. Adding a file descriptor that is already present in the set is a no-op, and does not produce anerror.FD_CLR()This macro removes the file descriptor fd from set. Removing a file descriptor that is not present in the set is a no-op, and does not producean error.FD_ISSET()select() modifies the contents of the sets according to the rules described below. After calling select(), the FD_ISSET() macro can be used totest if a file descriptor is still present in a set. FD_ISSET() returns nonzero if the file descriptor fd is present in set, and zero if it isnot.ArgumentsThe arguments of select() are as follows:readfdsThe file descriptors in this set are watched to see if they are ready for reading. A file descriptor is ready for reading if a read operationwill not block; in particular, a file descriptor is also ready on end-of-file.After select() has returned, readfds will be cleared of all file descriptors except for those that are ready for reading.writefdsThe file descriptors in this set are watched to see if they are ready for writing. A file descriptor is ready for writing if a write operationwill not block. However, even if a file descriptor indicates as writable, a large write may still block.After select() has returned, writefds will be cleared of all file descriptors except for those that are ready for writing.exceptfdsThe file descriptors in this set are watched for "exceptional conditions". For examples of some exceptional conditions, see the discussion ofPOLLPRI in poll(2).After select() has returned, exceptfds will be cleared of all file descriptors except for those for which an exceptional condition has occurred.nfds This argument should be set to the highest-numbered file descriptor in any of the three sets, plus 1. The indicated file descriptors in eachset are checked, up to this limit (but see BUGS).timeoutThe timeout argument is a timeval structure (shown below) that specifies the interval that select() should block waiting for a file descriptorto become ready. The call will block until either:• a file descriptor becomes ready;• the call is interrupted by a signal handler; or• the timeout expires.Note that the timeout interval will be rounded up to the system clock granularity, and kernel scheduling delays mean that the blocking intervalmay overrun by a small amount.If both fields of the timeval structure are zero, then select() returns immediately. (This is useful for polling.)If timeout is specified as NULL, select() blocks indefinitely waiting for a file descriptor to become ready.pselect()The pselect() system call allows an application to safely wait until either a file descriptor becomes ready or until a signal is caught.The operation of select() and pselect() is identical, other than these three differences:• select() uses a timeout that is a struct timeval (with seconds and microseconds), while pselect() uses a struct timespec (with seconds and nanosec‐onds).• select() may update the timeout argument to indicate how much time was left. pselect() does not change this argument.• select() has no sigmask argument, and behaves as pselect() called with NULL sigmask.sigmask is a pointer to a signal mask (see sigprocmask(2)); if it is not NULL, then pselect() first replaces the current signal mask by the one pointedto by sigmask, then does the "select" function, and then restores the original signal mask. (If sigmask is NULL, the signal mask is not modified dur‐ing the pselect() call.)Other than the difference in the precision of the timeout argument, the following pselect() call:ready = pselect(nfds, &readfds, &writefds, &exceptfds,timeout, &sigmask);is equivalent to atomically executing the following calls:sigset_t origmask;pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);ready = select(nfds, &readfds, &writefds, &exceptfds, timeout);pthread_sigmask(SIG_SETMASK, &origmask, NULL);The reason that pselect() is needed is that if one wants to wait for either a signal or for a file descriptor to become ready, then an atomic test isneeded to prevent race conditions. (Suppose the signal handler sets a global flag and returns. Then a test of this global flag followed by a call ofselect() could hang indefinitely if the signal arrived just after the test but just before the call. By contrast, pselect() allows one to first blocksignals, handle the signals that have come in, then call pselect() with the desired sigmask, avoiding the race.)The timeoutThe timeout argument for select() is a structure of the following type:struct timeval {time_t tv_sec; /* seconds */suseconds_t tv_usec; /* microseconds */};The corresponding argument for pselect() has the following type:struct timespec {time_t tv_sec; /* seconds */long tv_nsec; /* nanoseconds */};On Linux, select() modifies timeout to reflect the amount of time not slept; most other implementations do not do this. (POSIX.1 permits either behav‐ior.) This causes problems both when Linux code which reads timeout is ported to other operating systems, and when code is ported to Linux that reusesa struct timeval for multiple select()s in a loop without reinitializing it. Consider timeout to be undefined after select() returns.RETURN VALUEOn success, select() and pselect() return the number of file descriptors contained in the three returned descriptor sets (that is, the total number ofbits that are set in readfds, writefds, exceptfds). The return value may be zero if the timeout expired before any file descriptors became ready.On error, -1 is returned, and errno is set to indicate the error; the file descriptor sets are unmodified, and timeout becomes undefined.ERRORSEBADF An invalid file descriptor was given in one of the sets. (Perhaps a file descriptor that was already closed, or one on which an error has oc‐curred.) However, see BUGS.EINTR A signal was caught; see signal(7).EINVAL nfds is negative or exceeds the RLIMIT_NOFILE resource limit (see getrlimit(2)).EINVAL The value contained within timeout is invalid.ENOMEM Unable to allocate memory for internal tables.VERSIONSpselect() was added to Linux in kernel 2.6.16. Prior to this, pselect() was emulated in glibc (but see BUGS).CONFORMING TOselect() conforms to POSIX.1-2001, POSIX.1-2008, and 4.4BSD (select() first appeared in 4.2BSD). Generally portable to/from non-BSD systems supportingclones of the BSD socket layer (including System V variants). However, note that the System V variant typically sets the timeout variable before re‐turning, but the BSD variant does not.pselect() is defined in POSIX.1g, and in POSIX.1-2001 and POSIX.1-2008.NOTESAn fd_set is a fixed size buffer. Executing FD_CLR() or FD_SET() with a value of fd that is negative or is equal to or larger than FD_SETSIZE will re‐sult in undefined behavior. Moreover, POSIX requires fd to be a valid file descriptor.The operation of select() and pselect() is not affected by the O_NONBLOCK flag.On some other UNIX systems, select() can fail with the error EAGAIN if the system fails to allocate kernel-internal resources, rather than ENOMEM asLinux does. POSIX specifies this error for poll(2), but not for select(). Portable programs may wish to check for EAGAIN and loop, just as withEINTR.The self-pipe trickOn systems that lack pselect(), reliable (and more portable) signal trapping can be achieved using the self-pipe trick. In this technique, a signalhandler writes a byte to a pipe whose other end is monitored by select() in the main program. (To avoid possibly blocking when writing to a pipe thatmay be full or reading from a pipe that may be empty, nonblocking I/O is used when reading from and writing to the pipe.)Emulating usleep(3)Before the advent of usleep(3), some code employed a call to select() with all three sets empty, nfds zero, and a non-NULL timeout as a fairly portableway to sleep with subsecond precision.Correspondence between select() and poll() notificationsWithin the Linux kernel source, we find the following definitions which show the correspondence between the readable, writable, and exceptional condi‐tion notifications of select() and the event notifications provided by poll(2) and epoll(7):#define POLLIN_SET (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN |EPOLLHUP | EPOLLERR)/* Ready for reading */#define POLLOUT_SET (EPOLLWRBAND | EPOLLWRNORM | EPOLLOUT |EPOLLERR)/* Ready for writing */#define POLLEX_SET (EPOLLPRI)/* Exceptional condition */Multithreaded applicationsIf a file descriptor being monitored by select() is closed in another thread, the result is unspecified. On some UNIX systems, select() unblocks andreturns, with an indication that the file descriptor is ready (a subsequent I/O operation will likely fail with an error, unless another process re‐opens file descriptor between the time select() returned and the I/O operation is performed). On Linux (and some other systems), closing the file de‐scriptor in another thread has no effect on select(). In summary, any application that relies on a particular behavior in this scenario must be con‐sidered buggy.C library/kernel differencesThe Linux kernel allows file descriptor sets of arbitrary size, determining the length of the sets to be checked from the value of nfds. However, inthe glibc implementation, the fd_set type is fixed in size. See also BUGS.The pselect() interface described in this page is implemented by glibc. The underlying Linux system call is named pselect6(). This system call hassomewhat different behavior from the glibc wrapper function.The Linux pselect6() system call modifies its timeout argument. However, the glibc wrapper function hides this behavior by using a local variable forthe timeout argument that is passed to the system call. Thus, the glibc pselect() function does not modify its timeout argument; this is the behaviorrequired by POSIX.1-2001.The final argument of the pselect6() system call is not a sigset_t * pointer, but is instead a structure of the form:struct {const kernel_sigset_t *ss; /* Pointer to signal set */size_t ss_len; /* Size (in bytes) of objectpointed to by 'ss' */};This allows the system call to obtain both a pointer to the signal set and its size, while allowing for the fact that most architectures support a max‐imum of 6 arguments to a system call. See sigprocmask(2) for a discussion of the difference between the kernel and libc notion of the signal set.Historical glibc detailsGlibc 2.0 provided an incorrect version of pselect() that did not take a sigmask argument.In glibc versions 2.1 to 2.2.1, one must define _GNU_SOURCE in order to obtain the declaration of pselect() from <sys/select.h>.BUGSPOSIX allows an implementation to define an upper limit, advertised via the constant FD_SETSIZE, on the range of file descriptors that can be specifiedin a file descriptor set. The Linux kernel imposes no fixed limit, but the glibc implementation makes fd_set a fixed-size type, with FD_SETSIZE de‐fined as 1024, and the FD_*() macros operating according to that limit. To monitor file descriptors greater than 1023, use poll(2) or epoll(7) in‐stead.According to POSIX, select() should check all specified file descriptors in the three file descriptor sets, up to the limit nfds-1. However, the cur‐rent implementation ignores any file descriptor in these sets that is greater than the maximum file descriptor number that the process currently hasopen. According to POSIX, any such file descriptor that is specified in one of the sets should result in the error EBADF.Starting with version 2.1, glibc provided an emulation of pselect() that was implemented using sigprocmask(2) and select(). This implementation re‐mained vulnerable to the very race condition that pselect() was designed to prevent. Modern versions of glibc use the (race-free) pselect() systemcall on kernels where it is provided.On Linux, select() may report a socket file descriptor as "ready for reading", while nevertheless a subsequent read blocks. This could for examplehappen when data has arrived but upon examination has the wrong checksum and is discarded. There may be other circumstances in which a file descriptoris spuriously reported as ready. Thus it may be safer to use O_NONBLOCK on sockets that should not block.On Linux, select() also modifies timeout if the call is interrupted by a signal handler (i.e., the EINTR error return). This is not permitted byPOSIX.1. The Linux pselect() system call has the same behavior, but the glibc wrapper hides this behavior by internally copying the timeout to a localvariable and passing that variable to the system call.EXAMPLES#include <stdio.h>#include <stdlib.h>#include <sys/select.h>intmain(void){fd_set rfds;struct timeval tv;int retval;/* Watch stdin (fd 0) to see when it has input. */FD_ZERO(&rfds);FD_SET(0, &rfds);/* Wait up to five seconds. */tv.tv_sec = 5;tv.tv_usec = 0;retval = select(1, &rfds, NULL, NULL, &tv);/* Don't rely on the value of tv now! */if (retval == -1)perror("select()");else if (retval)printf("Data is available now.\n");/* FD_ISSET(0, &rfds) will be true. */elseprintf("No data within five seconds.\n");exit(EXIT_SUCCESS);}SEE ALSOaccept(2), connect(2), poll(2), read(2), recv(2), restart_syscall(2), send(2), sigprocmask(2), write(2), epoll(7), time(7)For a tutorial with discussion and examples, see select_tut(2).COLOPHONThis page is part of release 5.10 of the Linux man-pages project. A description of the project, information about reporting bugs, and the latest ver‐sion of this page, can be found at https://www.kernel.org/doc/man-pages/.Linux 2020-11-01 SELECT(2)
poll
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
struct pollfd *fds:对fd的封装,它时pollfd 数组的首地址。
The set of file descriptors to be monitored is specified in the fds argument, which is an array of structures of the following form:
struct pollfd {int fd; /* file descriptor 文件描述符*/ short events; /* requested events 要监听的请求的事件*/short revents; /* returned events 就绪时的事件*/
};
有四类处理输入的事件,三类处理输出的事件,三类处理异常的事件
nfds_t nfds:被poll管理的文件描述符的个数
int timeout:超时时间,负数:无线等待,正数:正常等待,0:直接返回
产生调用时,文件描述符数组需从用户态拷贝到内核态。内核态处理完fd事件后再拷贝给用户态。之后用户态判定哪些文件描述符处于就绪状态,从而处理。用户态代码需要遍历所有的文件描述符。文件描述符个数没有明确限制。变长数组可"任性扩容"。注意:poll在用户态保存文件描述符使用的是数组,而在内核态,会转换成链表,再拷贝会用户态时,又转换成了数组。
man poll
POLL(2) Linux Programmer's Manual POLL(2)NAMEpoll, ppoll - wait for some event on a file descriptorSYNOPSIS#include <poll.h>int poll(struct pollfd *fds, nfds_t nfds, int timeout);#define _GNU_SOURCE /* See feature_test_macros(7) */#include <signal.h>#include <poll.h>int ppoll(struct pollfd *fds, nfds_t nfds,const struct timespec *tmo_p, const sigset_t *sigmask);DESCRIPTIONpoll() performs a similar task to select(2): it waits for one of a set of file descriptors to become ready to perform I/O. The Linux-specific epoll(7)API performs a similar task, but offers features beyond those found in poll().The set of file descriptors to be monitored is specified in the fds argument, which is an array of structures of the following form:struct pollfd {int fd; /* file descriptor */short events; /* requested events */short revents; /* returned events */};The caller should specify the number of items in the fds array in nfds.The field fd contains a file descriptor for an open file. If this field is negative, then the corresponding events field is ignored and the reventsfield returns zero. (This provides an easy way of ignoring a file descriptor for a single poll() call: simply negate the fd field. Note, however,that this technique can't be used to ignore file descriptor 0.)The field events is an input parameter, a bit mask specifying the events the application is interested in for the file descriptor fd. This field maybe specified as zero, in which case the only events that can be returned in revents are POLLHUP, POLLERR, and POLLNVAL (see below).The field revents is an output parameter, filled by the kernel with the events that actually occurred. The bits returned in revents can include any ofthose specified in events, or one of the values POLLERR, POLLHUP, or POLLNVAL. (These three bits are meaningless in the events field, and will be setin the revents field whenever the corresponding condition is true.)If none of the events requested (and no error) has occurred for any of the file descriptors, then poll() blocks until one of the events occurs.The timeout argument specifies the number of milliseconds that poll() should block waiting for a file descriptor to become ready. The call will blockuntil either:• a file descriptor becomes ready;• the call is interrupted by a signal handler; or• the timeout expires.Note that the timeout interval will be rounded up to the system clock granularity, and kernel scheduling delays mean that the blocking interval mayoverrun by a small amount. Specifying a negative value in timeout means an infinite timeout. Specifying a timeout of zero causes poll() to return im‐mediately, even if no file descriptors are ready.The bits that may be set/returned in events and revents are defined in <poll.h>:POLLIN There is data to read.POLLPRIThere is some exceptional condition on the file descriptor. Possibilities include:• There is out-of-band data on a TCP socket (see tcp(7)).• A pseudoterminal master in packet mode has seen a state change on the slave (see ioctl_tty(2)).• A cgroup.events file has been modified (see cgroups(7)).POLLOUTWriting is now possible, though a write larger than the available space in a socket or pipe will still block (unless O_NONBLOCK is set).POLLRDHUP (since Linux 2.6.17)Stream socket peer closed connection, or shut down writing half of connection. The _GNU_SOURCE feature test macro must be defined (before in‐cluding any header files) in order to obtain this definition.POLLERRError condition (only returned in revents; ignored in events). This bit is also set for a file descriptor referring to the write end of a pipewhen the read end has been closed.POLLHUPHang up (only returned in revents; ignored in events). Note that when reading from a channel such as a pipe or a stream socket, this eventmerely indicates that the peer closed its end of the channel. Subsequent reads from the channel will return 0 (end of file) only after all out‐standing data in the channel has been consumed.POLLNVALInvalid request: fd not open (only returned in revents; ignored in events).When compiling with _XOPEN_SOURCE defined, one also has the following, which convey no further information beyond the bits listed above:POLLRDNORMEquivalent to POLLIN.POLLRDBANDPriority band data can be read (generally unused on Linux).POLLWRNORMEquivalent to POLLOUT.POLLWRBANDPriority data may be written.Linux also knows about, but does not use POLLMSG.ppoll()The relationship between poll() and ppoll() is analogous to the relationship between select(2) and pselect(2): like pselect(2), ppoll() allows an ap‐plication to safely wait until either a file descriptor becomes ready or until a signal is caught.Other than the difference in the precision of the timeout argument, the following ppoll() call:ready = ppoll(&fds, nfds, tmo_p, &sigmask);is nearly equivalent to atomically executing the following calls:sigset_t origmask;int timeout;timeout = (tmo_p == NULL) ? -1 :(tmo_p->tv_sec * 1000 + tmo_p->tv_nsec / 1000000);pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);ready = poll(&fds, nfds, timeout);pthread_sigmask(SIG_SETMASK, &origmask, NULL);The above code segment is described as nearly equivalent because whereas a negative timeout value for poll() is interpreted as an infinite timeout, anegative value expressed in *tmo_p results in an error from ppoll().See the description of pselect(2) for an explanation of why ppoll() is necessary.If the sigmask argument is specified as NULL, then no signal mask manipulation is performed (and thus ppoll() differs from poll() only in the precisionof the timeout argument).The tmo_p argument specifies an upper limit on the amount of time that ppoll() will block. This argument is a pointer to a structure of the followingform:struct timespec {long tv_sec; /* seconds */long tv_nsec; /* nanoseconds */};If tmo_p is specified as NULL, then ppoll() can block indefinitely.RETURN VALUEOn success, poll() returns a nonnegative value which is the number of elements in the pollfds whose revents fields have been set to a nonzero value(indicating an event or an error). A return value of zero indicates that the system call timed out before any file descriptors became read.On error, -1 is returned, and errno is set to indicate the cause of the error.ERRORSEFAULT fds points outside the process's accessible address space. The array given as argument was not contained in the calling program's addressspace.EINTR A signal occurred before any requested event; see signal(7).EINVAL The nfds value exceeds the RLIMIT_NOFILE value.EINVAL (ppoll()) The timeout value expressed in *ip is invalid (negative).ENOMEM Unable to allocate memory for kernel data structures.VERSIONSThe poll() system call was introduced in Linux 2.1.23. On older kernels that lack this system call, the glibc poll() wrapper function provides emula‐tion using select(2).The ppoll() system call was added to Linux in kernel 2.6.16. The ppoll() library call was added in glibc 2.4.CONFORMING TOpoll() conforms to POSIX.1-2001 and POSIX.1-2008. ppoll() is Linux-specific.NOTESThe operation of poll() and ppoll() is not affected by the O_NONBLOCK flag.On some other UNIX systems, poll() can fail with the error EAGAIN if the system fails to allocate kernel-internal resources, rather than ENOMEM asLinux does. POSIX permits this behavior. Portable programs may wish to check for EAGAIN and loop, just as with EINTR.Some implementations define the nonstandard constant INFTIM with the value -1 for use as a timeout for poll(). This constant is not provided in glibc.For a discussion of what may happen if a file descriptor being monitored by poll() is closed in another thread, see select(2).C library/kernel differencesThe Linux ppoll() system call modifies its tmo_p argument. However, the glibc wrapper function hides this behavior by using a local variable for thetimeout argument that is passed to the system call. Thus, the glibc ppoll() function does not modify its tmo_p argument.The raw ppoll() system call has a fifth argument, size_t sigsetsize, which specifies the size in bytes of the sigmask argument. The glibc ppoll()wrapper function specifies this argument as a fixed value (equal to sizeof(kernel_sigset_t)). See sigprocmask(2) for a discussion on the differencesbetween the kernel and the libc notion of the sigset.BUGSSee the discussion of spurious readiness notifications under the BUGS section of select(2).EXAMPLESThe program below opens each of the files named in its command-line arguments and monitors the resulting file descriptors for readiness to read(POLLIN). The program loops, repeatedly using poll() to monitor the file descriptors, printing the number of ready file descriptors on return. Foreach ready file descriptor, the program:• displays the returned revents field in a human-readable form;• if the file descriptor is readable, reads some data from it, and displays that data on standard output; and• if the file descriptors was not readable, but some other event occurred (presumably POLLHUP), closes the file descriptor.Suppose we run the program in one terminal, asking it to open a FIFO:$ mkfifo myfifo$ ./poll_input myfifoIn a second terminal window, we then open the FIFO for writing, write some data to it, and close the FIFO:$ echo aaaaabbbbbccccc > myfifoIn the terminal where we are running the program, we would then see:Opened "myfifo" on fd 3About to poll()Ready: 1fd=3; events: POLLIN POLLHUPread 10 bytes: aaaaabbbbbAbout to poll()Ready: 1fd=3; events: POLLIN POLLHUPread 6 bytes: cccccAbout to poll()Ready: 1fd=3; events: POLLHUPclosing fd 3All file descriptors closed; byeIn the above output, we see that poll() returned three times:• On the first return, the bits returned in the revents field were POLLIN, indicating that the file descriptor is readable, and POLLHUP, indicatingthat the other end of the FIFO has been closed. The program then consumed some of the available input.• The second return from poll() also indicated POLLIN and POLLHUP; the program then consumed the last of the available input.• On the final return, poll() indicated only POLLHUP on the FIFO, at which point the file descriptor was closed and the program terminated.Program source/* poll_input.cLicensed under GNU General Public License v2 or later.*/#include <poll.h>#include <fcntl.h>#include <sys/types.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \} while (0)intmain(int argc, char *argv[]){int nfds, num_open_fds;struct pollfd *pfds;if (argc < 2) {fprintf(stderr, "Usage: %s file...\n", argv[0]);exit(EXIT_FAILURE);}num_open_fds = nfds = argc - 1;pfds = calloc(nfds, sizeof(struct pollfd));if (pfds == NULL)errExit("malloc");/* Open each file on command line, and add it 'pfds' array */for (int j = 0; j < nfds; j++) {pfds[j].fd = open(argv[j + 1], O_RDONLY);if (pfds[j].fd == -1)errExit("open");printf("Opened \"%s\" on fd %d\n", argv[j + 1], pfds[j].fd);pfds[j].events = POLLIN;}/* Keep calling poll() as long as at least one file descriptor isopen */while (num_open_fds > 0) {int ready;printf("About to poll()\n");ready = poll(pfds, nfds, -1);if (ready == -1)errExit("poll");printf("Ready: %d\n", ready);/* Deal with array returned by poll() */for (int j = 0; j < nfds; j++) {char buf[10];if (pfds[j].revents != 0) {printf(" fd=%d; events: %s%s%s\n", pfds[j].fd,(pfds[j].revents & POLLIN) ? "POLLIN " : "",(pfds[j].revents & POLLHUP) ? "POLLHUP " : "",(pfds[j].revents & POLLERR) ? "POLLERR " : "");if (pfds[j].revents & POLLIN) {ssize_t s = read(pfds[j].fd, buf, sizeof(buf));if (s == -1)errExit("read");printf(" read %zd bytes: %.*s\n",s, (int) s, buf);} else { /* POLLERR | POLLHUP */printf(" closing fd %d\n", pfds[j].fd);if (close(pfds[j].fd) == -1)errExit("close");num_open_fds--;}}}}printf("All file descriptors closed; bye\n");exit(EXIT_SUCCESS);}SEE ALSOrestart_syscall(2), select(2), select_tut(2), epoll(7), time(7)COLOPHONThis page is part of release 5.10 of the Linux man-pages project. A description of the project, information about reporting bugs, and the latest ver‐sion of this page, can be found at https://www.kernel.org/doc/man-pages/.Linux 2020-04-11 POLL(2)
epoll
int epoll_create(int size);
int size:可忽略任意大于0的值即可。
NAMEepoll_create, epoll_create1 - open an epoll file descriptorSYNOPSIS#include <sys/epoll.h>int epoll_create(int size);int epoll_create1(int flags);DESCRIPTIONepoll_create() creates a new epoll(7) instance. Since Linux 2.6.8, the size argument is ignored, but must be greater than zero; see NOTES.
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epfd:epoll_create()创建的文件描述符
int op:EPOLL_CTL_ADD:添加,EPOLL_CTL_MOD:更新,EPOLL_CTL_DEL:删除
int fd:待监听的文件描述符
struct epoll_event *event:要监听的fd事件
NAMEepoll_ctl - control interface for an epoll file descriptorSYNOPSIS#include <sys/epoll.h>int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);DESCRIPTIONThis system call is used to add, modify, or remove entries in the interest list of the epoll(7) instance re‐ferred to by the file descriptor epfd. It requests that the operation op be performed for the target file de‐scriptor, fd.
int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);
int epfd:epoll_create()创建的文件描述符
epoll_event *events:就绪事件列表,就绪事件个数为int epoll_wait()的返回值
int maxevents:最多返回的事件个数,内核通过该值确定events数组的长度
int timeout:超时控制
NAMEepoll_wait, epoll_pwait - wait for an I/O event on an epoll file descriptorSYNOPSIS#include <sys/epoll.h>int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);int epoll_pwait(int epfd, struct epoll_event *events,int maxevents, int timeout,const sigset_t *sigmask);DESCRIPTIONThe epoll_wait() system call waits for events on the epoll(7) instance referred to by the file descriptorepfd. The buffer pointed to by events is used to return information from the ready list about file descrip‐tors in the interest list that have some events available. Up to maxevents are returned by epoll_wait(). Themaxevents argument must be greater than zero.
内核监听epoll的文件描述符时采用红黑树,就绪事件链表等数据结构。epoll的两种内置触发模式为ET(edge-trigger),LT(level-trigger)。
man epoll
EPOLL(7) Linux Programmer's Manual EPOLL(7)NAMEepoll - I/O event notification facilitySYNOPSIS#include <sys/epoll.h>DESCRIPTIONThe epoll API performs a similar task to poll(2): monitoring multiple file descriptors to see if I/O is possible on any of them. The epoll API can beused either as an edge-triggered or a level-triggered interface and scales well to large numbers of watched file descriptors.The central concept of the epoll API is the epoll instance, an in-kernel data structure which, from a user-space perspective, can be considered as acontainer for two lists:• The interest list (sometimes also called the epoll set): the set of file descriptors that the process has registered an interest in monitoring.• The ready list: the set of file descriptors that are "ready" for I/O. The ready list is a subset of (or, more precisely, a set of references to) thefile descriptors in the interest list. The ready list is dynamically populated by the kernel as a result of I/O activity on those file descriptors.The following system calls are provided to create and manage an epoll instance:• epoll_create(2) creates a new epoll instance and returns a file descriptor referring to that instance. (The more recent epoll_create1(2) extends thefunctionality of epoll_create(2).)• Interest in particular file descriptors is then registered via epoll_ctl(2), which adds items to the interest list of the epoll instance.• epoll_wait(2) waits for I/O events, blocking the calling thread if no events are currently available. (This system call can be thought of as fetch‐ing items from the ready list of the epoll instance.)Level-triggered and edge-triggeredThe epoll event distribution interface is able to behave both as edge-triggered (ET) and as level-triggered (LT). The difference between the two mech‐anisms can be described as follows. Suppose that this scenario happens:1. The file descriptor that represents the read side of a pipe (rfd) is registered on the epoll instance.2. A pipe writer writes 2 kB of data on the write side of the pipe.3. A call to epoll_wait(2) is done that will return rfd as a ready file descriptor.4. The pipe reader reads 1 kB of data from rfd.5. A call to epoll_wait(2) is done.If the rfd file descriptor has been added to the epoll interface using the EPOLLET (edge-triggered) flag, the call to epoll_wait(2) done in step 5 willprobably hang despite the available data still present in the file input buffer; meanwhile the remote peer might be expecting a response based on thedata it already sent. The reason for this is that edge-triggered mode delivers events only when changes occur on the monitored file descriptor. So,in step 5 the caller might end up waiting for some data that is already present inside the input buffer. In the above example, an event on rfd will begenerated because of the write done in 2 and the event is consumed in 3. Since the read operation done in 4 does not consume the whole buffer data,the call to epoll_wait(2) done in step 5 might block indefinitely.An application that employs the EPOLLET flag should use nonblocking file descriptors to avoid having a blocking read or write starve a task that ishandling multiple file descriptors. The suggested way to use epoll as an edge-triggered (EPOLLET) interface is as follows:a) with nonblocking file descriptors; andb) by waiting for an event only after read(2) or write(2) return EAGAIN.By contrast, when used as a level-triggered interface (the default, when EPOLLET is not specified), epoll is simply a faster poll(2), and can be usedwherever the latter is used since it shares the same semantics.Since even with edge-triggered epoll, multiple events can be generated upon receipt of multiple chunks of data, the caller has the option to specifythe EPOLLONESHOT flag, to tell epoll to disable the associated file descriptor after the receipt of an event with epoll_wait(2). When the EPOLLONESHOTflag is specified, it is the caller's responsibility to rearm the file descriptor using epoll_ctl(2) with EPOLL_CTL_MOD.If multiple threads (or processes, if child processes have inherited the epoll file descriptor across fork(2)) are blocked in epoll_wait(2) waiting onthe same epoll file descriptor and a file descriptor in the interest list that is marked for edge-triggered (EPOLLET) notification becomes ready, justone of the threads (or processes) is awoken from epoll_wait(2). This provides a useful optimization for avoiding "thundering herd" wake-ups in somescenarios.Interaction with autosleepIf the system is in autosleep mode via /sys/power/autosleep and an event happens which wakes the device from sleep, the device driver will keep the de‐vice awake only until that event is queued. To keep the device awake until the event has been processed, it is necessary to use the epoll_ctl(2)EPOLLWAKEUP flag.When the EPOLLWAKEUP flag is set in the events field for a struct epoll_event, the system will be kept awake from the moment the event is queued,through the epoll_wait(2) call which returns the event until the subsequent epoll_wait(2) call. If the event should keep the system awake beyond thattime, then a separate wake_lock should be taken before the second epoll_wait(2) call./proc interfacesThe following interfaces can be used to limit the amount of kernel memory consumed by epoll:/proc/sys/fs/epoll/max_user_watches (since Linux 2.6.28)This specifies a limit on the total number of file descriptors that a user can register across all epoll instances on the system. The limit isper real user ID. Each registered file descriptor costs roughly 90 bytes on a 32-bit kernel, and roughly 160 bytes on a 64-bit kernel. Cur‐rently, the default value for max_user_watches is 1/25 (4%) of the available low memory, divided by the registration cost in bytes.Example for suggested usageWhile the usage of epoll when employed as a level-triggered interface does have the same semantics as poll(2), the edge-triggered usage requires moreclarification to avoid stalls in the application event loop. In this example, listener is a nonblocking socket on which listen(2) has been called.The function do_use_fd() uses the new ready file descriptor until EAGAIN is returned by either read(2) or write(2). An event-driven state machine ap‐plication should, after having received EAGAIN, record its current state so that at the next call to do_use_fd() it will continue to read(2) orwrite(2) from where it stopped before.#define MAX_EVENTS 10struct epoll_event ev, events[MAX_EVENTS];int listen_sock, conn_sock, nfds, epollfd;/* Code to set up listening socket, 'listen_sock',(socket(), bind(), listen()) omitted */epollfd = epoll_create1(0);if (epollfd == -1) {perror("epoll_create1");exit(EXIT_FAILURE);}ev.events = EPOLLIN;ev.data.fd = listen_sock;if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1) {perror("epoll_ctl: listen_sock");exit(EXIT_FAILURE);}for (;;) {nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);if (nfds == -1) {perror("epoll_wait");exit(EXIT_FAILURE);}for (n = 0; n < nfds; ++n) {if (events[n].data.fd == listen_sock) {conn_sock = accept(listen_sock,(struct sockaddr *) &addr, &addrlen);if (conn_sock == -1) {perror("accept");exit(EXIT_FAILURE);}setnonblocking(conn_sock);ev.events = EPOLLIN | EPOLLET;ev.data.fd = conn_sock;if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock,&ev) == -1) {perror("epoll_ctl: conn_sock");exit(EXIT_FAILURE);}} else {do_use_fd(events[n].data.fd);}}}When used as an edge-triggered interface, for performance reasons, it is possible to add the file descriptor inside the epoll interface (EPOLL_CTL_ADD)once by specifying (EPOLLIN|EPOLLOUT). This allows you to avoid continuously switching between EPOLLIN and EPOLLOUT calling epoll_ctl(2) withEPOLL_CTL_MOD.Questions and answers0. What is the key used to distinguish the file descriptors registered in an interest list?The key is the combination of the file descriptor number and the open file description (also known as an "open file handle", the kernel's internalrepresentation of an open file).1. What happens if you register the same file descriptor on an epoll instance twice?You will probably get EEXIST. However, it is possible to add a duplicate (dup(2), dup2(2), fcntl(2) F_DUPFD) file descriptor to the same epoll in‐stance. This can be a useful technique for filtering events, if the duplicate file descriptors are registered with different events masks.2. Can two epoll instances wait for the same file descriptor? If so, are events reported to both epoll file descriptors?Yes, and events would be reported to both. However, careful programming may be needed to do this correctly.3. Is the epoll file descriptor itself poll/epoll/selectable?Yes. If an epoll file descriptor has events waiting, then it will indicate as being readable.4. What happens if one attempts to put an epoll file descriptor into its own file descriptor set?The epoll_ctl(2) call fails (EINVAL). However, you can add an epoll file descriptor inside another epoll file descriptor set.5. Can I send an epoll file descriptor over a UNIX domain socket to another process?Yes, but it does not make sense to do this, since the receiving process would not have copies of the file descriptors in the interest list.6. Will closing a file descriptor cause it to be removed from all epoll interest lists?Yes, but be aware of the following point. A file descriptor is a reference to an open file description (see open(2)). Whenever a file descriptoris duplicated via dup(2), dup2(2), fcntl(2) F_DUPFD, or fork(2), a new file descriptor referring to the same open file description is created. Anopen file description continues to exist until all file descriptors referring to it have been closed.A file descriptor is removed from an interest list only after all the file descriptors referring to the underlying open file description have beenclosed. This means that even after a file descriptor that is part of an interest list has been closed, events may be reported for that file de‐scriptor if other file descriptors referring to the same underlying file description remain open. To prevent this happening, the file descriptormust be explicitly removed from the interest list (using epoll_ctl(2) EPOLL_CTL_DEL) before it is duplicated. Alternatively, the application mustensure that all file descriptors are closed (which may be difficult if file descriptors were duplicated behind the scenes by library functions thatused dup(2) or fork(2)).7. If more than one event occurs between epoll_wait(2) calls, are they combined or reported separately?They will be combined.8. Does an operation on a file descriptor affect the already collected but not yet reported events?You can do two operations on an existing file descriptor. Remove would be meaningless for this case. Modify will reread available I/O.9. Do I need to continuously read/write a file descriptor until EAGAIN when using the EPOLLET flag (edge-triggered behavior)?Receiving an event from epoll_wait(2) should suggest to you that such file descriptor is ready for the requested I/O operation. You must considerit ready until the next (nonblocking) read/write yields EAGAIN. When and how you will use the file descriptor is entirely up to you.For packet/token-oriented files (e.g., datagram socket, terminal in canonical mode), the only way to detect the end of the read/write I/O space isto continue to read/write until EAGAIN.For stream-oriented files (e.g., pipe, FIFO, stream socket), the condition that the read/write I/O space is exhausted can also be detected bychecking the amount of data read from / written to the target file descriptor. For example, if you call read(2) by asking to read a certain amountof data and read(2) returns a lower number of bytes, you can be sure of having exhausted the read I/O space for the file descriptor. The same istrue when writing using write(2). (Avoid this latter technique if you cannot guarantee that the monitored file descriptor always refers to astream-oriented file.)Possible pitfalls and ways to avoid themo Starvation (edge-triggered)If there is a large amount of I/O space, it is possible that by trying to drain it the other files will not get processed causing starvation. (Thisproblem is not specific to epoll.)The solution is to maintain a ready list and mark the file descriptor as ready in its associated data structure, thereby allowing the application toremember which files need to be processed but still round robin amongst all the ready files. This also supports ignoring subsequent events you receivefor file descriptors that are already ready.o If using an event cache...If you use an event cache or store all the file descriptors returned from epoll_wait(2), then make sure to provide a way to mark its closure dynami‐cally (i.e., caused by a previous event's processing). Suppose you receive 100 events from epoll_wait(2), and in event #47 a condition causes event#13 to be closed. If you remove the structure and close(2) the file descriptor for event #13, then your event cache might still say there are eventswaiting for that file descriptor causing confusion.One solution for this is to call, during the processing of event 47, epoll_ctl(EPOLL_CTL_DEL) to delete file descriptor 13 and close(2), then mark itsassociated data structure as removed and link it to a cleanup list. If you find another event for file descriptor 13 in your batch processing, youwill discover the file descriptor had been previously removed and there will be no confusion.VERSIONSThe epoll API was introduced in Linux kernel 2.5.44. Support was added to glibc in version 2.3.2.CONFORMING TOThe epoll API is Linux-specific. Some other systems provide similar mechanisms, for example, FreeBSD has kqueue, and Solaris has /dev/poll.NOTESThe set of file descriptors that is being monitored via an epoll file descriptor can be viewed via the entry for the epoll file descriptor in theprocess's /proc/[pid]/fdinfo directory. See proc(5) for further details.The kcmp(2) KCMP_EPOLL_TFD operation can be used to test whether a file descriptor is present in an epoll instance.SEE ALSOepoll_create(2), epoll_create1(2), epoll_ctl(2), epoll_wait(2), poll(2), select(2)COLOPHONThis page is part of release 5.10 of the Linux man-pages project. A description of the project, information about reporting bugs, and the latest ver‐sion of this page, can be found at https://www.kernel.org/doc/man-pages/.Linux 2019-03-06 EPOLL(7)
Reference
Linux Programmer’s Manual
相关文章:
select、poll、epoll
select、poll、epoll select int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); int nfds:被select管理的文件描述符的个数,最大描述符编号1fd_set *readfds:读文件描述符集合fd_se…...
rollup的基本使用 基本配置与处理各种文件
rollup rollup是一个javascript的模块化打包工具 可以帮助我们编译小的代码到一个大的负载的代码中 比如一个库或者一个应用 rollup与webpack的区别 rollup主要针对ES Module进行打包 另外webpack通常可以通过各种loader处理各种各样的文件 以及处理他们的依赖关系 rollup更多…...
ubuntu-debian系-redhat系
debian系 包类型:.deb包 本地安装包安装工具:dpkg 本地包管理命令:dpkg -i package 安装包 dpkg -r package 卸载包 dpkg -l package 查看已安装包 远程安装包安装工具:apt / apt-get 远程包管理命令:apt-get apt-cac…...
Altium Designer 18中原理图DRC编译和PCB DRC检查-AD DRC
一、原理图编译 原理图检查的主要内容有: 1、元件位号冲突。也即多个元件编号相同,例如两个电容在原理图中都被命名为C2,显然肯定是无法生成PCB的。 2、网络悬浮。也即网络标号没有附着在电气走线上,一般这种是人操作失误&…...
zipfile — 访问 ZIP 压缩文件
zipfile — 访问 ZIP 压缩文件 1.概述 zipfile 模块可用于操作 ZIP 存档文件,.zip 是 PC 程序 PKZIP 推广的格式 2.测试数据 为了演示用,你需要创建以下三个文件 1.README.txt 内容如下,注意最后一行为空行 The examples for the zipfil…...
检查nmos管是否损坏
NCEP85T14 功率mos管为例 以NMOS举例,只用万用表二极管档测量MOS管的好坏-电子发烧友网 NMOS的D极和S极之间有一个寄生二极管,方向为S到D,利用二极管单向导电性以及MOS管导通时寄生二极管截止的特性,可以快速测量MOS好坏。 1、测…...
第七章 - 聚合函数(count,avg,sum,max,min)和一些数学函数
第七章 - 聚合函数使用别名 ascount() 计数avg() 平均值sum() 求和max() 最大值min() 最小值一些数学计算函数Abs()Cos()Exp()Mod()Pi()radians()Sin()Sqrt()Power()Ceil()Floor()使用别名 as 在SQL中可以使用 as 来为一个字段或者一个值设置新的别名下面聚合函数的使用中就会…...
Typescript的原始据类型和Any类型
最新的ECMAScript标准定义了8中数据类型: 7种原始类型: BooleanNullUndefinedNumberBigintStringSymbol和 Object 除 Object 以外的所有类型都是不可变的 (值本身无法被改变》。例如,与C语言不同JavaScript 中字符串是不可变的 (译注: 如,Ja…...
[python入门㊼] - python类的高级函数
目录 ❤ 类的高级函数 ❤ __str__ ❤ __getattr__ ❤ __setattr__ ❤ __call__ ❤ 类的高级函数 今天来为大家介绍几个类中的高级函数,它们也是类中的内置函数。通过使用它们, 会让我们在进行类开发的时候更加的顺手,接下来我们就…...
【Windows】使用Fiddler 工具对手机进行接口监听
目录 工具下载 配置Fidder 手机端获取证书 过滤指定接口 工具下载 CSDN下载地址 其他下载地址 配置Fidder 安装后,打开进入如下界面 在fiddler菜单项选择Tools -> Options -> HTTPS 勾选【Decrypt HTTPS traffic 】 下拉框默认:【from al…...
SpringCloudAlibab-nacos
一、介绍注册中心配置中心的整合SpringCloudAlibaba中文地址:https://github.com/alibaba/spring-cloud-alibaba/blob/2.2.x/README-zh.md下载地址:https://github.com/alibaba/nacos/访问:http://localhost:8848/nacos/二、使用1、添加依赖&…...
从一致性角度考虑推荐冷启动长尾推荐问题(二)
前言:在推荐系统中user&item emb往往是最重要的特征之一,在冷启动和长尾优化的工作中,往往也是优化的重点,相当一部分工作是围绕着emb优化展开,所以这里单独开了一章。4)emb分布一致性主要思路在于冷启内容emb和高…...
电脑c盘满了怎么清理,c盘空间清理
电脑c盘满了怎么清理?电脑C盘满了可能是因为您的操作系统、程序文件、下载文件、临时文件、垃圾文件等占用了太多的存储空间。所以,我们就需要进行一些操作和清理。 一.清理电脑C盘的方法 清理临时文件和垃圾文件。在Windows上,您可以使用系…...
vite的基本使用
vite 浏览器原生支持模块化 浏览器原生加载的缺点 1.必须明确的写上后缀名 2.如果某一个模块 加载跟多其他的js文件 那么这些js文件都需要被依次加载 浏览器需要将所有的js文件请求下来 发送跟多的http请求(效率也是非常低的) 3.如果代码中由typescrip…...
JavaScript 字符串(String) 对象
JavaScript 是一种流行的编程语言,可以用于开发各种 Web 应用程序和移动应用程序。在 JavaScript 中,字符串是一种非常常见的数据类型,可以使用 JavaScript 字符串(String)对象来处理。本文将详细介绍 JavaScript 字符…...
小知识点:Mac M1/M2 VMware Fusion 安装 Centos 7.9(ARM 64 版本)
最近换了 Mac M2 芯片的笔记本,用原来的 Centos 镜像安装虚拟机直接报错 “无法打开此虚拟机的电源,因为它需要使用 X86 计算机架构,而该架构与此 Arm 计算机架构主机不兼容。” 安装流程前置一、下载镜像二、安装虚拟机三、配置静态 IP四、安…...
Nginx 新增模块 http_image_filter_module 来实现动态生成缩略图
前言 通过 nginx 的 HttpImageFilterModule 模块裁剪过大的图片到指定大小,这个nginx自带的模块是默认关闭的,所以需要重新编译nginx加上此模块。 一、编译 nginx 1.查看 nginx 模块 由于nginx 是之前装好的,这里需要先看一下是否安装了H…...
detach,主线程终止后子线程会结束吗
此前,我对detach的理解是,当主线程退出后,子线程能够继续存在。实际上,当主线程退出后,子线程也随之结束了。先看一个例子: #include <iostream> #include <thread> #include <unistd.h>…...
2023年云计算的发展趋势如何?还值得学习就业吗?
一、2023年云计算的发展将迎来新篇章 随着政策的正式放开,2023年的经济开始慢慢复苏,云计算在疫情期间支撑了复工复产,那么在今年对于云计算发展的限制将进一步的放开。Gartner的数据显示,到2023年,全球公共云支出将达…...
ROS2 入门应用 请求和应答(C++)
ROS2 入门应用 请求和应答(C)1. 创建功能包2. 创建源文件2.1. 服务端2.2. 客户端3. 添加依赖关系4. 添加编译信息4.1. 添加搜索库4.2. 增加可执行文件4.3. 增加可执行文件位置5. 编译和运行1. 创建功能包 在《ROS2 入门应用 工作空间》中已创建和加载了…...
华为机试题:HJ73 计算日期到天数转换(python)
文章目录博主精品专栏导航知识点详解1、input():获取控制台(任意形式)的输入。输出均为字符串类型。1.1、input() 与 list(input()) 的区别、及其相互转换方法2、print() :打印输出。3、整型int() :将指定进制…...
将springboot项目生成可依赖的jar,并引入到项目中
1、将springboot项目生成可依赖的jar包的方法 SpringBoot项目默认打包的是可运行jar包,也可以打包成不可运行的jar包。 能打成可运行的jar包是因为,Spring Boot 项目引入了 spring-boot-maven-plugin 依赖包。 spring-boot-maven-plugin具有repackage …...
小红书搜索关键词布局指南,这4种词一定要把握好
在小红书搜索关键词布局,是提升搜索推流的重要方法,今天跟你讲清楚小红书搜索关键词布局怎么做~做小红书的都知道,小红书的主要流量来源一个是推荐,另一个就是搜索,关键词决定了你的精准人群,那…...
安全研发人员能力模型窥探
能力 是一个比较抽象的概念,不同的行业、管理者、研发人员对能力的认知都会有差异。另外,作为研发团队的相应的职级定级、绩效考核的基础,一个“大家普遍认可”的能力的模型是非常重要的。这是比职级模型更高层的一个基本模型,所谓…...
【面试总结】Linux篇·操作及原理篇
【面试总结】Linux篇原理篇1.介绍一下inode2.说一下Linux系统的目录结构3.说一下Linux系统的文件类型4.如何在Linux上配置一个IP地址5.Linux负载是什么?6.Linux中的软链接和硬链接有什么区别?1.介绍一下inode 硬盘的最小存储单位是扇区(Sector)…...
C++中如何实现用异或运算找出数组中只出现一次的数字???
文章目录1、异或运算符的运算1、异或运算符的运算 问题描述: 给出一个指定的数组,只有一个数出现一次,剩下都出现两次,找出出现一次的数字。指定数组为[1,2,2,1,3,4,3]。 样例输出:4 #include<iostream> using…...
红黑树的历史和由来。
一个数组,1,2,3,4,5,...n; 一共n个数字。1、直接查找想要查询第n个数字,直接搜索,就是n次查询。ps:那么问题来了,这样查询也太慢了,有什么改进的呢?2、二分查找这个时候,二分查找更快。不过就是…...
蓝库云|制造业数字化转型为何转不动?资料处理很重要
数字化转型已经成为每个产业势在必行的课题,没有人会怀疑数字化技术与科技能解放的生产力能量,但为什么看似美好的愿景,实行起来却如此缓慢?蓝库云认为这是因为没有盖好「资料治理」的地基。 面对不断变化的法令规范要求…...
【python学习笔记】 :Lambda 函数
Lambda 函数是 Python 中的匿名函数。有些人将它们简称为lambdas,它们的语法如下: lambda arguments: expressionlambda 关键字可以用来创建一个 lambda 函数,紧跟其后的是参数列表和用冒号分割开的单个表达式。例如,lambda x: 2…...
Nginx的proxy buffer参数设置
1. proxy_buffering 语法:proxy_buffering on|off 默认值:proxy_buffering on 上下文:http,server,location作用:该指令开启从后端被代理服务器的响应body缓冲。 如果proxy_buffering开启,nginx假定被代理的后端服务器会以最…...
开一家网站建设公司好/互联网广告推广是什么
题目: 程序说明: 直接使用for循环1到2019,不断判断每个数是否含有2,0,1,9中的其中一个数字,若是,则将它进行立方以后再相加即可。 全部代码: x0 for i in range(1,2020)…...
自由贸易试验区网站建设方案/短视频获客系统
1、HOG特征: 方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子。它通过计算和统计图像局部区域的梯度方向直方图来构成特征。Hog特征结合SVM分类器已经被广泛应用于图像…...
好的网站建设网/西安专业seo
关于线性与条带化下LVM增加磁盘数据分布的讨论一、环境介绍二、线性模式逻辑卷创建逻辑卷删除三、条带化逻辑卷创建逻辑卷删除LVM有两种模式:线性模式:先写满组成线性逻辑卷的第一个物理卷,再向第2个物理卷中写入数据,以此类推&am…...
网站安全如何做/深圳网站建设开发公司
首先把应用程序发布,发布到文件系统在winR里面输入inetmgr,进入iis点击网站右键添加网站选择右边的属性,选择处理程序映射然后打开处理程序映射,选择右边的可执行的文件时找到aspnet_isapi.dll的文件在选择右边的添加通配符脚本映射这里的可执…...
网站统计代码添加/专业seo培训学校
[oracle] to_date() 与 to_char() 日期和字符串转换 to_date("要转换的字符串","转换的格式") 两个参数的格式必须匹配,否则会报错。 即按照第二个参数的格式解释第一个参数。 to_char(日期,"转换格式" ) 即把给定的日期按照“转换…...
专做国外采购的网站/站长之家关键词查询
使用这句代码: temp pd.rolling_mean(temp, 2) 会报以下错误: AttributeError: module pandas has no attribute rolling_mean 解决方法: 将代码改为:temp temp .rolling(2).mean() 觉得有用请留下你的赞 ^_^...