Chinaunix首页 | 论坛 | 博客
  • 博客访问: 11700637
  • 博文数量: 8065
  • 博客积分: 10002
  • 博客等级: 中将
  • 技术积分: 96708
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-16 17:06
文章分类

全部博文(8065)

文章存档

2008年(8065)

分类: 服务器与存储

2008-07-18 10:00:16

1、dd命令的源代码:
while (1)
  {
   if (r_partial + r_full >= max_records)
  break;

   /* Zero the buffer before reading, so that if we get a read error,
  whatever data we are able to read is followed by zeros.
  This minimizes data loss. */
   if ((conversions_mask & C_SYNC) && (conversions_mask & C_NOERROR))
  memset (ibuf,
    (conversions_mask & (C_BLOCK | C_UNBLOCK)) ? ' ' : '\0',   设定内存空间为0
    input_blocksize);

   nread = iread (STDIN_FILENO, ibuf, input_blocksize);

   if (nread == 0)
  break;      /* EOF. */

   if (nread < 0)
  {
   error (0, errno, _("reading %s"), quote (input_file));
   if (conversions_mask & C_NOERROR)
    {
     print_stats ();
     /* Seek past the bad block if possible. */
     if (!advance_input_after_read_error (input_blocksize - partread))
    {
     exit_status = EXIT_FAILURE;

     /* Suppress duplicate diagnostics. */
     input_seekable = false;
     input_seek_errno = ESPIPE;
    }
     if ((conversions_mask & C_SYNC) && !partread)
    /* Replace the missing input with null bytes and
     proceed normally. */
    nread = 0;
     else
    continue;
    }
   else
    {
     /* Write any partial block. */
     exit_status = EXIT_FAILURE;
     break;
    }
  }

   n_bytes_read = nread;
   advance_input_offset (nread);

   if (n_bytes_read < input_blocksize)
  {
   r_partial++;
   partread = n_bytes_read;
   if (conversions_mask & C_SYNC)
    {
     if (!(conversions_mask & C_NOERROR))
    /* If C_NOERROR, we zeroed the block before reading. */
    memset (ibuf + n_bytes_read,
      (conversions_mask & (C_BLOCK | C_UNBLOCK)) ? ' ' : '\0',
      input_blocksize - n_bytes_read);
     n_bytes_read = input_blocksize;
    }
  }
   else
  {
   r_full++;
   partread = 0;
  }

   if (ibuf == obuf)    /* If not C_TWOBUFS. */
  {
   size_t nwritten = iwrite (STDOUT_FILENO, obuf, n_bytes_read);
   w_bytes += nwritten;
   if (nwritten != n_bytes_read)
    {
     error (0, errno, _("writing %s"), quote (output_file));
     return EXIT_FAILURE;
    }
   else if (n_bytes_read == input_blocksize)
    w_full++;
   else
    w_partial++;
   continue;
  }




static size_t
iwrite (int fd, char const *buf, size_t size)
{
size_t total_written = 0;

while (total_written < size)
  {
   ssize_t nwritten;
   process_signals ();
   nwritten = write (fd, buf + total_written, size - total_written);
   if (nwritten < 0)
  {
   if (errno != EINTR)
    break;
  }
   else if (nwritten == 0)
  {
   /* Some buggy drivers return 0 when one tries to write beyond
    a device's end. (Example: Linux 1.2.13 on /dev/fd0.)
    Set errno to ENOSPC so they get a sensible diagnostic. */
   errno = ENOSPC;
   break;
  }
   else
  total_written += nwritten;
  }

return total_written;
}




static ssize_t
iread (int fd, char *buf, size_t size)
{
for (;;)
  {
   ssize_t nread;
   process_signals ();
   nread = read (fd, buf, size);
   if (! (nread < 0 && errno == EINTR))
  return nread;
  }
}
dd_copy函数
dd_copy (void)
{
char *ibuf, *bufstart;  /* Input buffer. */
/* These are declared static so that even though we don't free the
   buffers, valgrind will recognize that there is no "real" leak. */
static char *real_buf;  /* real buffer address before alignment */
static char *real_obuf;
ssize_t nread;    /* Bytes read in the current block. */

/* If nonzero, then the previously read block was partial and
   PARTREAD was its size. */
size_t partread = 0;

int exit_status = EXIT_SUCCESS;
size_t n_bytes_read;

/* Leave at least one extra byte at the beginning and end of `ibuf'
   for conv=swab, but keep the buffer address even. But some peculiar
   device drivers work only with word-aligned buffers, so leave an
   extra two bytes. */

/* Some devices require alignment on a sector or page boundary
   (e.g. character disk devices). Align the input buffer to a
   page boundary to cover all bases. Note that due to the swab
   algorithm, we must have at least one byte in the page before
   the input buffer; thus we allocate 2 pages of slop in the
   real buffer. 8k above the blocksize shouldn't bother anyone.

   The page alignment is necessary on any linux system that supports
   either the SGI raw I/O patch or Steven Tweedies raw I/O patch.
   It is necessary when accessing raw (i.e. character special) disk
   devices on Unixware or other SVR4-derived system. */

real_buf = xmalloc (input_blocksize + INPUT_BLOCK_SLOP);
ibuf = real_buf;
ibuf += SWAB_ALIGN_OFFSET;  /* allow space for swab */

ibuf = ptr_align (ibuf, page_size);

if (conversions_mask & C_TWOBUFS)
  {
   /* Page-align the output buffer, too. */
   real_obuf = xmalloc (output_blocksize + OUTPUT_BLOCK_SLOP);
   obuf = ptr_align (real_obuf, page_size);
  }
else
  {
   real_obuf = NULL;
   obuf = ibuf;
  }

if (skip_records != 0)
  {
   skip (STDIN_FILENO, input_file, skip_records, input_blocksize, ibuf);
   /* POSIX doesn't say what to do when dd detects it has been
  asked to skip past EOF, so I assume it's non-fatal if the
  call to 'skip' returns nonzero. FIXME: maybe give a warning. */
  }

if (seek_records != 0)
  {
   uintmax_t write_records = skip (STDOUT_FILENO, output_file,
           seek_records, output_blocksize, obuf);

   if (write_records != 0)
  {
   memset (obuf, 0, output_blocksize);

   do
    if (iwrite (STDOUT_FILENO, obuf, output_blocksize)
    != output_blocksize)
     {
    error (0, errno, _("writing to %s"), quote (output_file));
    quit (EXIT_FAILURE);
     }
   while (--write_records != 0);
  }
  }

if (max_records == 0)
  return exit_status;

while (1)
  {
   if (r_partial + r_full >= max_records)
  break;

   /* Zero the buffer before reading, so that if we get a read error,
  whatever data we are able to read is followed by zeros.
  This minimizes data loss. */
   if ((conversions_mask & C_SYNC) && (conversions_mask & C_NOERROR))
  memset (ibuf,
    (conversions_mask & (C_BLOCK | C_UNBLOCK)) ? ' ' : '\0',
    input_blocksize);

   nread = iread (STDIN_FILENO, ibuf, input_blocksize);

   if (nread == 0)
  break;      /* EOF. */

   if (nread < 0)
  {
   error (0, errno, _("reading %s"), quote (input_file));
   if (conversions_mask & C_NOERROR)
    {
     print_stats ();
     /* Seek past the bad block if possible. */
     if (!advance_input_after_read_error (input_blocksize - partread))
    {
     exit_status = EXIT_FAILURE;

     /* Suppress duplicate diagnostics. */
     input_seekable = false;
     input_seek_errno = ESPIPE;
    }
     if ((conversions_mask & C_SYNC) && !partread)
    /* Replace the missing input with null bytes and
     proceed normally. */
    nread = 0;
     else
    continue;
    }
   else
    {
     /* Write any partial block. */
     exit_status = EXIT_FAILURE;
     break;
    }
  }

   n_bytes_read = nread;
   advance_input_offset (nread);

   if (n_bytes_read < input_blocksize)
  {
   r_partial++;
   partread = n_bytes_read;
   if (conversions_mask & C_SYNC)
    {
     if (!(conversions_mask & C_NOERROR))
    /* If C_NOERROR, we zeroed the block before reading. */
    memset (ibuf + n_bytes_read,
      (conversions_mask & (C_BLOCK | C_UNBLOCK)) ? ' ' : '\0',
      input_blocksize - n_bytes_read);
     n_bytes_read = input_blocksize;
    }
  }
   else
  {
   r_full++;
   partread = 0;
  }

   if (ibuf == obuf)    /* If not C_TWOBUFS. */
  {
   size_t nwritten = iwrite (STDOUT_FILENO, obuf, n_bytes_read);
   w_bytes += nwritten;
   if (nwritten != n_bytes_read)
    {
     error (0, errno, _("writing %s"), quote (output_file));
     return EXIT_FAILURE;
    }
   else if (n_bytes_read == input_blocksize)
    w_full++;
   else
    w_partial++;
   continue;
  }

   /* Do any translations on the whole buffer at once. */

   if (translation_needed)
  translate_buffer (ibuf, n_bytes_read);

   if (conversions_mask & C_SWAB)
  bufstart = swab_buffer (ibuf, &n_bytes_read);
   else
  bufstart = ibuf;

   if (conversions_mask & C_BLOCK)
    copy_with_block (bufstart, n_bytes_read);
   else if (conversions_mask & C_UNBLOCK)
  copy_with_unblock (bufstart, n_bytes_read);
   else
  copy_simple (bufstart, n_bytes_read);
  }

/* If we have a char left as a result of conv=swab, output it. */
if (char_is_saved)
  {
   if (conversions_mask & C_BLOCK)
    copy_with_block (&saved_char, 1);
   else if (conversions_mask & C_UNBLOCK)
  copy_with_unblock (&saved_char, 1);
   else
  output_char (saved_char);
  }

if ((conversions_mask & C_BLOCK) && col > 0)
  {
   /* If the final input line didn't end with a '\n', pad
  the output block to `conversion_blocksize' chars. */
   size_t i;
   for (i = col; i < conversion_blocksize; i++)
  output_char (space_character);
  }

if ((conversions_mask & C_UNBLOCK) && col == conversion_blocksize)
  /* Add a final '\n' if there are exactly `conversion_blocksize'
    characters in the final record. */
  output_char (newline_character);

/* Write out the last block. */
if (oc != 0)
  {
   size_t nwritten = iwrite (STDOUT_FILENO, obuf, oc);
   w_bytes += nwritten;
   if (nwritten != 0)
  w_partial++;
   if (nwritten != oc)
  {
   error (0, errno, _("writing %s"), quote (output_file));
   return EXIT_FAILURE;
  }
  }

if ((conversions_mask & C_FDATASYNC) && fdatasync (STDOUT_FILENO) != 0)
  {
   if (errno != ENOSYS && errno != EINVAL)
  {
   error (0, errno, _("fdatasync failed for %s"), quote (output_file));
   exit_status = EXIT_FAILURE;
  }
   conversions_mask |= C_FSYNC;
  }

if (conversions_mask & C_FSYNC)
  while (fsync (STDOUT_FILENO) != 0)
   if (errno != EINTR)
  {
   error (0, errno, _("fsync failed for %s"), quote (output_file));
   return EXIT_FAILURE;
  }

return exit_status;
}

2、dd的本质

本质就是按照bs的大小作为一次Iread和Iwrite:

size_t nwritten = iwrite (STDOUT_FILENO, obuf, n_bytes_read);
阅读(1286) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~