Dup

در سیستم‌عاملهای شبه یونیکس، dup و dup2 دو فراخوان سیستمی هستند که به کمک آن‌ها می‌توان کپی جدیدی از یک توصیف‌گر پرونده ایجاد کرد. این توصیف‌گر جدید، عملاً مانند یک کپی عمل نمی‌کند، بلکه مانند یک توصیف‌گر مستعار برای توصیف‌گر قدیمی عمل می‌کند. در استاندارد پازیکس، این دو فراخوان سیستمی در فایل سرایند unistd.h و به شکل زیر تعریف شده‌اند:

int dup(int fildes);
int dup2(int fildes, int fildes2);

فراخوان سیستمی اول (dup)، توصیف‌گری که قرار است کپی شود را به عنوان آرگومان دریافت می‌کند و در برگشت، یک کپی از آن را برمی‌گرداند. این کپی، کوچکترین توصبف‌گری آزادی است که در حال حاضر استفاده نمی‌شود. به عنوان یک راه جایگزین برای کپی کردن یک توصیف‌گر پرونده در یک مکان نامشخص، می‌توان از فراخوان سیستمی دیگری به نام fcntl با پارامتر  F_DUPFD  استفاده کرد. فراخوان سیستمی دوم (dup2)، یک کپی از oldfd را در newfd قرار می‌دهد. اگر newfd در حال استفاده باشد، ابتدا بسته شده و سپس تغییر خواهد یافت.

اهمیت dup برای پوسته‌های یونیکس 
پوسته‌های یونیکس از فراخوان سیستمی dup2 برای هدایت کردن ورودی/خروجی استاندارد به جایی دیگر استفاده می‌کنند. همینطور پوسته‌های یونیکس از این فراخوان‌های سیستمی برای برقرار کردن ارتباط بین فرایندها با استفاده از لوله‌ها استفاده می‌کنند. در مثال زیر، برنامه program1 اجرا شده و خروجی خود را به program2 ارسال می‌کند. ارتباط بین program1 و program2 به وسیلهٔ لوله‌ها صورت می‌گیرد. program1 و program2 در دو فرایند مستقل اجرا می‌شوند.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

/*function prototypes */
void die(const char*);
 
int main(int argc, char **argv)
{
 
	int pdes[2];
	pid_t child;
 
	if(-1 == (pipe(pdes)))
		die("pipe()");
 
	child = fork();
	if(child == (pid_t)(-1))
        	die("fork()"); /* fork failed */
 
	if((pid_t)0 == child)
	{
        	/* child process */

        	close(1);       /* close stdout */
        	
        	if(-1 == dup(pdes[1]))
        		die("dup()");
        	
        	/* now stdout and pdes[1] are equivalent (dup returns lowest free descriptor) */

        	if(-1 == (execlp("program1", "program1", "arg1", NULL)))
        		die("execlp()");

		_exit(EXIT_SUCCESS);
	} else
	{
        	/* parent process */

        	close(0);       /* close stdin */
        	
        	if(-1 == dup(pdes[0]))
        		die("dup()");

        	/* now stdin and pdes[0] are equivalent (dup returns lowest free descriptor) */

        	if(-1 == (execlp("program2", "program2", "arg1", NULL)))
        		die("execlp()");

		exit(EXIT_SUCCESS);
	}
 
	return 0;
}

void die(const char *msg)
{
	perror(msg);
	exit(EXIT_FAILURE);
}

منابع

References 

فراخوان‌های سیستمی
کتابخانه پازیکس سی