k...@aspodata.se writes: > Katola2: > ... >> void another_print_start(char *name, char *what){ >> >> char c[3] = " :"; >> >> c[2] = name[0] & ~0x20; >> >> write(2, c+2, 1); >> write(2, name+1, strlen(name) -1); >> write(2, c, 2); >> write(2, what, strlen(what)); >> >> } > > Why not just use writev(2) and write it one system call ?
The idea behind writev is to avoid userspace block memory copies prior to doing a system call which will end up copying all the memory contents into kernel memory. In order to achieve this, a vector of struct iovec structures each specifiyng the location and size of a single area is used. A struct iovec is struct iovec { void *iov_base; size_t iov_len; }; On a 64-bit system, this means that an additional 16 bytes of data need to be copied by the kernel for every area used by writev. For this to be worthwhile, the average size of an area should be more than 33 bytes, otherwise, writev will end up doing more copying than userspace code had need to create a continuous area before doing the system call. And then, there's also the userspace code needed to initialize the vector. For the example above, this would be iovs->iov_base = c + 2; iovs->iov_len = 2; iovs[1].iov_base = name + 1; iovs[1].iov_len = strlen(name) - 1; iovs[2].iov_base = c; iovs[2].iov_len = 2; iovs[3].iov_base = what; iovs[3].iov_len = strlen(what); compared to name_len = strlen(name); what_len = strlen(what); total = name_len + what_len + 3; p = buf = alloca(total); memcpy(p, name, name_len); p += name_len; *p++ = ' '; memcpy(p, what, what_len); p += what_len; *p++ = ':'; *p = ' '; that's 3 lines of code less which is "not great". In addition to this, both write and writev may end up writing less data than requested and the code for restarting a partially completed writev is more complicated than the same for write. _______________________________________________ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng