linux C语言write()函数

448 篇文章 27 订阅

man 2 write

WRITE(2)                                                             Linux Programmer's Manual                                                            WRITE(2)

NAME
       write - write to a file descriptor	//写入文件描述符

SYNOPSIS
       #include <unistd.h>

       ssize_t write(int fd, const void *buf, size_t count);

DESCRIPTION
       write() writes up to count bytes from the buffer pointed buf to the file referred to by the file descriptor fd.

       The  number  of  bytes  written  may be less than count if, for example, there is insufficient space on the underlying physical medium, or the RLIMIT_FSIZE
       resource limit is encountered (see setrlimit(2)), or the call was interrupted by a signal handler after having written less than count  bytes.   (See  also
       pipe(7).)

       For  a seekable file (i.e., one to which lseek(2) may be applied, for example, a regular file) writing takes place at the current file offset, and the file
       offset is incremented by the number of bytes actually written.  If the file was open(2)ed with O_APPEND, the file offset is first set to  the  end  of  the
       file before writing.  The adjustment of the file offset and the write operation are performed as an atomic step.

       POSIX requires that a read(2) which can be proved to occur after a write() has returned returns the new data.  Note that not all filesystems are POSIX con‐
       forming.
       //write() 将缓冲区指向的 buf 中的 count 个字节写入文件描述符 fd 所引用的文件。

       //写入的字节数可能少于 count,例如,底层物理介质上的空间不足,或者遇到 RLIMIT_FSIZE 资源限制(参见 setrlimit(2)),或者调用被信号处理程序中断后写入少于 count 个字节。
       // (另请参见管道 (7)。)

       //对于可查找文件(即可以应用 lseek(2) 的文件,例如常规文件),写入发生在当前文件偏移量处,并且文件偏移量增加实际写入的字节数。
       //如果使用 O_APPEND 打开(2)文件,则文件偏移量在写入之前首先设置为文件末尾。
       //文件偏移量的调整和写入操作作为原子步骤执行。

       //POSIX 要求可以证明在 write() 返回后发生的 read(2) 返回新数据。请注意,并非所有文件系统都符合 POSIX。

RETURN VALUE
       On success, the number of bytes written is returned (zero indicates nothing was written).  It is not an error if this number is smaller than the number  of
       bytes requested; this may happen for example because the disk device was filled.  See also NOTES.

       On error, -1 is returned, and errno is set appropriately.

       If  count  is  zero  and  fd  refers  to a regular file, then write() may return a failure status if one of the errors below is detected.  If no errors are
       detected, or error detection is not performed, 0 will be returned without causing any other effect.  If count is zero and fd refers to a file other than  a
       regular file, the results are not specified.
       //成功时,返回写入的字节数(零表示未写入任何内容)。 
       //如果此数字小于请求的字节数,则不是错误; 例如,这可能是因为磁盘设备已满。 另见注释。

        //出错时,返回 -1,并适当设置 errno。

        //如果 count 为零并且 fd 引用常规文件,则如果检测到以下错误之一,则 write() 可能会返回失败状态。 
        //如果没有检测到错误,或者没有进行错误检测,则返回 0,不会产生任何其他影响。 如果 count 为零并且 fd 引用的文件不是常规文件,则不指定结果。

ERRORS
       EAGAIN The  file  descriptor  fd refers to a file other than a socket and has been marked nonblocking (O_NONBLOCK), and the write would block.  See open(2)
              for further details on the O_NONBLOCK flag.
              //文件描述符 fd 指除了socket之外的文件,并且已被标记为非阻塞(O_NONBLOCK),写入将阻塞。 
              //有关 O_NONBLOCK 标志的更多详细信息,请参见 open(2)。

       EAGAIN or EWOULDBLOCK
              The file descriptor fd refers to a socket and has been marked nonblocking (O_NONBLOCK), and the write would block.  POSIX.1-2001 allows either error
              to be returned for this case, and does not require these constants to have the same value, so a portable application should check for both possibil‐
              ities.
              //文件描述符 fd 是一个socket并且已被标记为非阻塞 (O_NONBLOCK),写入将阻塞。
              //这里的阻塞是指:内核写缓冲可能不够空间(参考:https://www.zhihu.com/question/533504297)
              //POSIX.1-2001 允许在这种情况下返回任一错误,并且不要求这些常量具有相同的值,因此可移植应用程序应检查这两种可能性。

       EBADF  fd is not a valid file descriptor or is not open for writing.
       			//fd 不是有效的文件描述符或未打开写入。

       EDESTADDRREQ
              fd refers to a datagram socket for which a peer address has not been set using connect(2).
              //fd 指的是尚未使用 connect(2) 为其设置对等地址的数据报套接字。

       EDQUOT The user's quota of disk blocks on the filesystem containing the file referred to by fd has been exhausted.
       			//包含 fd 引用的文件的文件系统上用户的磁盘块配额已用完。(配额是啥?怎么设置的?)

       EFAULT buf is outside your accessible address space.
       			//buf 在您可访问的地址空间之外。

       EFBIG  An attempt was made to write a file that exceeds the implementation-defined maximum file size or the process's file size limit, or  to  write  at  a
              position past the maximum allowed offset.
              //尝试写入超过实现定义的最大文件大小或进程的文件大小限制的文件,或写入超过最大允许偏移量的位置。

       EINTR  The call was interrupted by a signal before any data was written; see signal(7).
       //在写入任何数据之前调用被信号中断; 见信号(7)。

       EINVAL fd is attached to an object which is unsuitable for writing; or the file was opened with the O_DIRECT flag, and either the address specified in buf,
              the value specified in count, or the current file offset is not suitably aligned.
              //fd 附着在不适合书写的对象上; 
              //或者文件是使用 O_DIRECT 标志打开的,并且 buf 中指定的地址、count 中指定的值或当前文件偏移量未适当对齐。

       EIO    A low-level I/O error occurred while modifying the inode.
       		//修改 inode 时发生低级 I/O 错误。

       ENOSPC The device containing the file referred to by fd has no room for the data.
       //包含 fd 引用的文件的设备没有数据空间。

       EPERM  The operation was prevented by a file seal; see fcntl(2).
       //文件封印阻止了该操作; 参见 fcntl(2)。

       EPIPE  fd is connected to a pipe or socket whose reading end is closed.  When this happens the writing process will also receive a SIGPIPE signal.   (Thus,
              the write return value is seen only if the program catches, blocks or ignores this signal.)
              //fd 连接到读取端关闭的管道或套接字。 
              //当这种情况发生时,写入过程也会收到一个 SIGPIPE 信号。 (因此,只有当程序捕获、阻塞或忽略此信号时,才会看到写入返回值。)

       Other errors may occur, depending on the object connected to fd.

CONFORMING TO
       SVr4, 4.3BSD, POSIX.1-2001.

       Under SVr4 a write may be interrupted and return EINTR at any point, not just before any data is written.

NOTES
       A  successful  return  from  write() does not make any guarantee that data has been committed to disk.  In fact, on some buggy implementations, it does not
       even guarantee that space has successfully been reserved for the data.  The only way to be sure is to call fsync(2) after you are  done  writing  all  your
       data.

       If a write() is interrupted by a signal handler before any bytes are written, then the call fails with the error EINTR; if it is interrupted after at least
       one byte has been written, the call succeeds, and returns the number of bytes written.

       On Linux, write() (and similar system calls) will transfer at most 0x7ffff000 (2,147,479,552) bytes, returning the number of  bytes  actually  transferred.
       (This is true on both 32-bit and 64-bit systems.)
       //write() 的成功返回并不能保证数据已提交到磁盘。 
       //事实上,在一些有缺陷的实现中,它甚至不能保证已成功为数据保留空间。 
       //唯一可以确定的方法是在完成所有数据的写入后调用 fsync(2)。

        //如果 write() 在写入任何字节之前被信号处理程序中断,则调用失败并返回错误 EINTR; 
        //如果在至少写入一个字节后中断,则调用成功,并返回写入的字节数。

        //在 Linux 上,write()(和类似的系统调用)将最多传输 0x7ffff000 (2,147,479,552) 字节,返回实际传输的字节数。
        //(在 32 位和 64 位系统上都是如此。)

BUGS
       According to POSIX.1-2008/SUSv4 Section XSI 2.9.7 ("Thread Interactions with Regular File Operations"):

           All  of  the following functions shall be atomic with respect to each other in the effects specified in POSIX.1-2008 when they operate on regular files
           or symbolic links: ...

       Among the APIs subsequently listed are write() and writev(2).  And among the effects that should be atomic across threads (and processes)  are  updates  of
       the  file offset.  However, on Linux before version 3.14, this was not the case: if two processes that share an open file description (see open(2)) perform
       a write() (or writev(2)) at the same time, then the I/O operations were not atomic with respect updating the file offset, with the result that  the  blocks
       of data output by the two processes might (incorrectly) overlap.  This problem was fixed in Linux 3.14.
       //根据 POSIX.1-2008/SUSv4 Section XSI 2.9.7(“线程与常规文件操作的交互”):

            //以下所有函数在对常规文件或符号链接进行操作时,在 POSIX.1-2008 中指定的效果中相互之间应是原子的: ...

        //随后列出的 API 包括 write() 和 writev(2)。 
        //跨线程(和进程)应该是原子的影响之一是文件偏移量的更新。 
        //但是,在 3.14 之前的 Linux 上,情况并非如此:如果共享打开文件描述(参见 open(2))的两个进程同时执行 write()(或 writev(2)),则 I /O 操作在更新文件偏移方面不是原子的,因此两个进程输出的数据块可能(不正确地)重叠。 
        //此问题已在 Linux 3.14 中修复。

SEE ALSO
       close(2), fcntl(2), fsync(2), ioctl(2), lseek(2), open(2), pwrite(2), read(2), select(2), writev(2), fwrite(3)

COLOPHON
       This  page  is part of release 4.04 of the Linux man-pages project.  A description of the project, information about reporting bugs, and the latest version
       of this page, can be found at http://www.kernel.org/doc/man-pages/.

Linux                                                                       2015-07-23                                                                    WRITE(2)
 Manual page write(2) line 65/106 (END) (press h for help or q to quit)


20230816

Linux中的C语言write()函数

在Linux系统编程中,write()函数是一个重要的系统调用,用于将数据从缓冲区写入文件或套接字。本文将深入探讨write()函数的用法和实现细节。

1. 函数声明与参数

在unistd.h头文件中,我们可以找到write函数的声明:

#include <unistd.h>

ssize_t write(int fd, const void *buf, size_t count);

write()函数有三个参数:

  • fd: 文件描述符,标识待写入的文件或者套接字。
  • buf: 指向要写入的数据的缓冲区。
  • count: 要写入的字节数。

返回值为实际写入的字节数,错误时返回-1,并设置errno。

2. 使用示例

以下是使用write()函数将字符串写入文件的示例:

#include <fcntl.h>
#include <unistd.h>

int main() {
    int filedesc = open("testfile.txt", O_WRONLY | O_APPEND);

    if (filedesc < 0) {
        return -1;
    }

    if (write(filedesc, "This will be output to testfile.txt\n", 36) != 36) {
        write(2, "There was an error writing to testfile.txt\n", 43);
        return -1;
    }

    return 0;
}

3. 错误处理

write()函数调用失败时,它会返回-1并设置全局变量errno来指示错误类型。以下是一些可能的错误代码:

  • EBADF: 参数fd不是有效的文件描述符或者不支持写操作。
  • EIO: I/O错误发生。
  • ENOSPC: 设备上没有剩余空间。

4. 注意事项

  • 写操作始终从文件的当前位置开始,如果需要在特定位置写入数据,需要先使用lseek()函数更改位置。
  • 如果write()在写入前被信号中断,则它可以重新启动,并写入尽可能多的数据,但这不是必须的。所以,write()可能只写入部分数据。

5. 性能考虑

write()函数每次调用都涉及内核态和用户态之间的切换,频繁调用可能导致性能下降。为了提高效率,可以考虑使用如writev()等聚集I/O函数,或者使用缓冲区批量写入数据。

参考文章

  1. Linux manual page - write(2)
  2. The GNU C Library: I/O Primitives

ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
本书所附光盘使用说明 本光盘中包括了书中所有示例的源代码和书中所有的插图,具体说明如下。 程序代码文件夹中包含了本书的所有源代码。 程序代码\chapter02 文件夹中包含了第2章的示例源程序。其中hello.c和hello.h是2.3.2的源代码,gdb.c是2.4.1的源代码,test.c是动手练练的源代码。 程序代码\chapter06 文件夹中包含了第6章的示例源程序。其中pointer1.c是6.2.2的第一个源代码,pointer2.c是6.2.2的第二个源代码,pointer3.c是6.2.2的第三个源代码,pointer4.c是6.2.3的第一个源代码,pointer5.c是6.2.3的第二个源代码,pointer6.c是6.2.3的第三个源代码,pointer7.c是6.2.3的第四个源代码。 程序代码\chapter08 文件夹中包含了第8章的示例源程序。其中binary_tree.c是二叉树的源代码,list.c是线性链表的源代码。 程序代码\chapter09 文件夹中包含了第9章的示例源程序。其中lock.c是文件锁的源代码,seri.c和seri.h是串口设置的源代码,read_seri.c是读串口的源代码,write_seri.c是写串口的源代码。 程序代码\chapter10 文件夹中包含了第10章的示例源程序。其中alarm_read.c是设置信号函数的源代码,dameon.c是守护进程的源代码,zombie.c是僵尸进程的源代码。 程序代码\chapter11 文件夹中包含了第11章的示例源程序。其中socklib.c是网络相关通用函数的源代码,tracert.c是traceroute的源代码,webserv.c是web服务器的源代码。 程序代码\chapter12 文件夹中包含了第12章的示例源程序。其中skull.c是skull驱动程序的源代码,s3c2410fb.c和s3c2410fb.h是LCD驱动的源代码。 程序代码\chapter13 文件夹中包含了第13章的示例源程序。其中args_cmd.h是解析命令相关的头文件,ctrl.c和ctrl.h是控制命令的源代码,proc_cmd.c是具体操作的源代码,thread.c和thread.h是线程相关的源代码,types.h是类型相关的源代码,net_send.h是网络相关的源代码。 书中插图包含了本书所有的插图。
Linux系统下使用C语言实现音频混音可通过调用相关的库函数来实现。以下是实现音频混音的一种简单方法: 首先,需要使用ALSA库来进行音频的输入和输出操作。ALSA是Linux提供的一个音频输入输出的API,通过它我们可以获取音频设备的信息并进行操作。 接着,我们使用C语言编写程序来打开音频设备,并设置相关参数。可以使用`snd_pcm_open`函数来打开音频设备,并使用`snd_pcm_set_params`函数来设置音频流的采样率、声道数和采样格式等参数。 然后,我们创建一个缓冲区来存储音频数据。可以使用`malloc`函数来分配一块内存作为缓冲区,并使用`snd_pcm_hw_params`函数来获取音频流的缓冲区大小。 接下来,我们使用循环读取和写入音频数据。通过`snd_pcm_readi`函数从音频设备读取原始音频数据,并使用`snd_pcm_writei`函数将经过处理的音频数据写入到播放设备中。可以在读取和写入音频数据时进行混音操作,将多个音频数据按一定算法进行混合。 最后,我们关闭音频设备并释放相关资源。可以使用`snd_pcm_drain`函数来等待音频缓冲区中的音频数据播放完毕,然后使用`snd_pcm_close`函数来关闭音频设备。 需要注意的是,由于涉及到音频数据的采样率、声道数和采样格式等参数,所以在编写程序前需要先了解音频设备的具体参数,以便正确地进行设置和操作。 以上是使用C语言Linux系统下实现音频混音的一种简单方法,当然,在实际应用中还可以使用更复杂的算法和更高级的库函数来实现更精细的混音效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dontla

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值