GVKun编程网logo

Unix/Linux编程实践教程–od在OS X的实现(linux中od命令)

7

本文的目的是介绍Unix/Linux编程实践教程–od在OSX的实现的详细情况,特别关注linux中od命令的相关信息。我们将通过专业的研究、有关数据的分析等多种方式,为您呈现一个全面的了解Unix/

本文的目的是介绍Unix/Linux编程实践教程–od在OS X的实现的详细情况,特别关注linux中od命令的相关信息。我们将通过专业的研究、有关数据的分析等多种方式,为您呈现一个全面的了解Unix/Linux编程实践教程–od在OS X的实现的机会,同时也不会遗漏关于I/O 重定向和管道 ——《Unix/Linux 编程实践教程》读书笔记(第 10 章)、I/O重定向和管道——《Unix/Linux编程实践教程》读书笔记(第10章)、Linux vs Unix - Linux与Unix到底的不同、linux – 从windows转移到* nix编程平台的知识。

本文目录一览:

Unix/Linux编程实践教程–od在OS X的实现(linux中od命令)

Unix/Linux编程实践教程–od在OS X的实现(linux中od命令)

环境:OS X 10.12.4

抱歉,本文章并不是关于Ollydbg的实现(笑)。

照旧man 1 od

od 是一个能把指定的文件或者标准输入按照用户定义的格式打印。(
The od utility is a filter which displays the specified files,or standard input if no files are specified,in a user specified format.)

乍一看这个命令的参数有一大堆,本文只挑一部分去实现,包括-A指定地址基数,-j跳过指定数目的字符,-N最多打印n个字符。-t输出格式。

实现起来并不难,只是参数比较多,实现起来比较繁琐,同样可以使用前面写的xc_file.c缓存输入。

od.c 不完全实现,BUG N多

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

enum{
    DEC,HEX,OCT,NOADDR
}addr_base,output_format;

void xc_open(char *aFName);
void xc_readFromStdin(void);
int xc_getchar(void);
void xc_close(void);
void xc_moveto(int offset,int whence);

void print_char(int ch,int size);
void print_addr(int addr);
void format_error(void);
int dump_bytes(char *str);

/* Usage: od [-A base] [-j skip] [-N length] [-t type] [file] */
/* default for od -t o2 [file] if no option is given */
int main(int ac,char *av[])
{
    addr_base = OCT;
    int skip = 0;
    int length = INT_MAX;
    int cnt = 0;
    int size = 2; /* output size */
    int i,j;
    int end_print = 0;
    int bytes_print;
    output_format = OCT;
    while(--ac && (*++av)[0] == '-'){
        switch(*++av[0]){
            case 'A':
                switch((*++av)[0]){
                    case 'd':
                        addr_base = DEC;
                        break;
                    case 'o':
                        break;
                    case 'x':
                        addr_base = HEX;
                        break;
                    case 'n':
                        addr_base = NOADDR;
                        break;
                    default:
                        format_error();
                }
                --ac; /* substract because read a option value */
                break;
            case 'j':
                skip = dump_bytes(*++av);
                if(skip <= 0)
                    format_error();
                --ac; /* substract because read a option value */
                break;
            case 'N':
                length = atoi(*++av);
                if(length <= 0)
                    format_error();
                --ac; /* substract because read a option value */
                break;
            case 't':
                switch((*++av)[0]){
                    case 'd':   /* signed decimal */
                    case 'u':   /* unsigned decimal */
                        /* do not reconize signed or unsigned */
                        output_format = DEC;
                        break;
                    case 'o':   /* octal */
                        output_format = OCT;
                        break;
                    case 'x':   /* hexadecimal */
                        output_format = HEX;
                        break;
                    default:
                        format_error();
                }
                switch(*++av[0]){
                    case 'C':
                        size = sizeof(char);
                        break;
                    case 'S':
                        size = sizeof(short);
                        break;
                    case 'I':
                        size = sizeof(int);
                        break;
                    case 'L':
                        size = sizeof(long);
                        break;
                    default:
                        if(*av[0] >= '0' && *av[0] <= '9')
                        {
                            size = atoi(av[0]); 
                            if(size <= 0)
                                format_error();
                        }else
                            format_error();
                        break;
                }
                --ac; /* substract because read a option value */
                break;
        }
    }
    if(ac == 1)
        xc_open(*av);
    else
        xc_readFromStdin();

    /* default `skip` is zero if `-j` option is not given */
    xc_moveto(skip,SEEK_SET);
    cnt = skip;
    while(cnt < length && !end_print){
        int size_count = 0;
        int buf[sizeof(long)];
        int tmpValue = 0;
        int ch;
        print_addr(cnt);        

        while(cnt < length && !end_print){
            size_count = 0;
            while(size_count < size && cnt < length && (ch = xc_getchar()) != EOF){
                buf[size_count++] = ch;
                cnt++;
            }
            tmpValue = 0;
            for(i = size_count - 1; i >= 0; --i)
                tmpValue = tmpValue * 256 + buf[i];
            print_char(tmpValue,size);
            if(ch == EOF || cnt == length){
                // int tmp = cnt;
                // while(++tmp % 16)
                // ;
                // tmp = (tmp - cnt) / size;
                // while(tmp--)
                // print_char(' ',size);
                end_print = 1;
                while(++cnt % 16)
                    ;
            }
            if(cnt % 16 == 0){
                /* 16 bytes per line */
                printf("\n");
                break;
            }
        }
    }
    print_addr(cnt);
    printf("\n");
    xc_close();
    return 0;
}
void print_char(int ch,int size)
{
    switch(output_format){
        case OCT:
            switch(size){
                case 1:
                    printf(" %.3o",ch);
                    break;
                case 2:
                    printf(" %.6o",ch);
                    break;
                case 4:
                    break;
            }
            break;
        case DEC:
            printf("%d ",ch);
            break;
        case HEX:
            printf("%x ",ch);
            break;
    }
}
void print_addr(int addr)
{
    switch(addr_base){
        case OCT:
            printf("%.7o ",addr);
            break;
        case HEX:
            printf("%.7x ",addr);
            break;
        case DEC:
            printf("%.7d ",addr);
            break;
        case NOADDR:
            printf("%7.7s "," ");
            break;
    }
}
int dump_bytes(char *str)
{
    int ans = 0;
    while(*str >= '0' && *str <= '9'){
        ans = ans * 10 + (*str - '0');
        str++;
    }
    switch(*str){
        case '\0':
            break;
        case 'b': /* block(512 bytes) */
            ans *= 512;
            break;
        case 'k': /* kilobyte */
            ans *= 1024;
            break;
        case 'm': /* megabyte */
            ans *= 1024 * 1024;
            break;
    }
    return ans;
}
void format_error(void)
{
    fprintf(stderr,"Usage: od [-A base] [-j skip] [-N length] [-t type] [file]\n");
    exit(1);
}

xc_file.c

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

/* BUFSIZ define in stdio.h,commonly is 1024 */
static unsigned char chBuf[BUFSIZ];
static int fd = -1;
static char fName[BUFSIZ];
static int chCur;
static int chSum;

void xc_readFromStdin(void)
{
    /* define in unistd.h */
    fd = STDIN_FILENO;
}

void xc_open(char *aFName)
{
    if((fd = open(aFName,O_RDONLY)) == -1){
        perror(aFName);
        exit(1);
    }
    strcpy(fName,aFName); /* record which file is opened */
    chCur = chSum = 0;
}

int xc_reload(void)
{
    int bytes_read;
    if((bytes_read = read(fd,chBuf,BUFSIZ)) > 0){
        chCur = 0;
        chSum = bytes_read;
        return chBuf[chCur++];
    }else if(bytes_read == -1){
        perror(fName);
        exit(1);
    }else if (bytes_read == 0)
        return EOF;
}

int xc_getchar(void)
{
    if(fd == -1)
        return EOF;
    if(chSum == chCur)
        return xc_reload();
    return chBuf[chCur++];
}

void xc_close(void)
{
    if(fd != -1)
    {
        if(close(fd) == -1){
            perror(fName);
            exit(1);
        }
        fd = -1;
    }
}
void xc_moveto(int offset,int whence)
{
    if(fd == -1)
        return ;
    if(lseek(fd,offset,whence) == -1){
        perror("target position are illegal");
        exit(1);
    }
}

效果

I/O 重定向和管道 ——《Unix/Linux 编程实践教程》读书笔记(第 10 章)

I/O 重定向和管道 ——《Unix/Linux 编程实践教程》读书笔记(第 10 章)

1、I/O 重定向的概念与原因 及 标准输入、输出的标准错误的定义

所以的 Unix I/O 重定向都基于标准数据流的原理。三个数据了分别如下:

    1)标准输入 —— 需要处理的数据流

    2)标准输出 —— 结果数据流

    3)标准错误输出 —— 错误消息流


概念:所以的 Unix 工具都使用文件描述符 0、1 和 2。标准输入文件的描述符是 0, 标准输出的文件描述符是 1,而标准错误输出的文件描述符则是 2。Unix 假设文件描述符 0、1、2 已经被打开,可以分别进行读写操作。

通常通过 shell 命令行运行 Unix 系统工具时,stdin、stdout、stderr 连接在终端上。因此,工具从键盘读取数据并且把输出和错误消息写到屏幕。

大部分的 Unix 工具处理从文件或标准输入读入的数据。如果在命令行上给出了文件名,工具将从文件读取数据。若无文件名,程序则从标准输入读取数据。从另一方面说,大多数程序并不接收输出文件名;它们总是将结果写到文件描述符 1, 并将错误消息写到文件描述符 2。如果希望将进程的输出写道文件或另一个进程的输入去,就必须重定向相应的文件描述符。

重定向 I/O 的是 shell 而不是程序

最低可用文件描述符(lowest-available-fd)原则:文件描述符是一个数组的索引号。每个进程都有其打开的一组文件。这些打开的文件被保持在一个数组中。文件描述符即为某文件在此数组中的索引。当打开文件时,为此文件安排的描述符总是此数组中最低可用位置的索引。

将文件描述符 0、1、2 的概念和最低可用文件描述符原则结合使用,即可理解 I/O 重定向的工作原理


2、重定向标准 I/O 到文件

(1)如何将 stdin 定向到文件

a、close-then-open 策略

close(0);
int fd = open(file, O_RDONLY);


b、open-close-dup-close 策略
int oldfd = open(file, O_RDONLY);
#ifndef DUP2
    close(0);
    int newfd = dup(oldfd);
#else
    int newfd = dup2(oldfd, 0);
#endif
close(oldfd);


man 2 dup
#include <unistd.h>

int dup(int oldfd);
int dup2(int oldfd, int newfd);

系统调用 dup 复制了文件描述符 oldfd。而 dup2 将 oldfd 文件描述符复制给 newfd。两个文件描述符都指向同一个打开的文件。这两个调用都返回新的文件描述符,若发生错误,则返回 - 1。


c、open-dup2-close 策略


(2)重定向到文件

共有 3 个基本的概念,利用它们是的 Unix 下的程序可以轻易地将标准输入、输出和错误信息输出连接到文件:

    a、标准输入、输出以及错误输出分别对应于文件描述符 0、1、2;

    b、内核总是使用最低可用文件描述符;

    c、文件描述符集合通过 exec 调用传递,且不会被改变。

例子:

/*
 * who_to_file.c
 * purpose: show how to redirect output for another program
 * idea: fork, then in the child, redirect output, then exec
 */

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(void)
{
    pid_t   pid;
    int     fd;

    printf("about to run who into a file\n");

    /* create a new process or quit */
    if ((pid = fork()) == -1)
    {
        perror("fork");
        exit(1);
    }

    /* child does the work */
    if (pid == 0)
    {
        close(1);
        fd = creat("userlist", 0644);
        execlp("who", "who", NULL);
        perror("execlp");
        exit(1);
    }

    /* parent waits then reports */
    else
    {
        wait(NULL);
        printf("done running who. results in userlist\n");
    }

    return 0;
}


3、管道编程

(1)创建管道

man 2 pipe
#include <unistd.h>

int pipe(int pipefd[2]);

系统调用 pipe 创建管道并将两端连接到两个文件描述符。pipefd [0] 为读数据端的文件描述符,而 pipefd [1] 则为写数据端的文件描述符。


(2)技术细节:管道并非文件

a、从管道中读数据

    管道读取阻塞:当进程试图从管道中读数据时,进程被挂起直到数据被写进管道。

    管道的读取结束标志:当所以的写操作关闭了管道的写数据端时,试图从管道读取数据的调用返回 0,意味着文件的结束。

    多个读操作可能会引起麻烦:管道是一个队列。当进程从管道中读取数据之后,数据已经不存在了。

b、向管道中写数据

    写入数据阻塞直到管道有空间去容纳新的数据

    写入必须保证一个最小的块大小:POSIX 标准规定内涵不会拆分小于 512 字节的块。而 Linux 则保证管道中可以存在 4096 字节的连续缓存。如果两个进程向管道写数据,并且没一个进程都限制其消息不打由于 512 字节,那么这些消息都不会被内核拆分。

    若无读操作在读数据,则写操作执行失败:如果所以的读操作都已将管道的读取端关闭,那么对管道的写入调用将会执行失败。如果在这种情况下,数据还可以被接收的话,为了避免数据丢失,内核采用了两种方法来通知进程:“此时的写操作是无意义的”。首先,内核发送 SIGPIPE 消息给进程。若进程被终止,则无任何事情发生。否则 write 调用返回 - 1, 并且将 errno 置为 EPIPE。

例子:

/*
 * pipe.c -
 *      demonstrates how to create a pipeline from one process to another
 * takes two args, each a command, and connectes
 * argv[1]s output to input of argv[2]
 * usage: pipe command1 command2
 * effect: command1 | command2
 * limitations: commands do not take arguments
 * users execlp() since known number of args
 * note: exchange child and parent and watch fun
 */

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

#define oops(m, x)  { perror(m); exit(x); }

int main(int argc, char **argv)
{
    int     thepipe[2],
            newfd,
            pid;

    if (argc != 3)
    {
        fprintf(stderr, "usage: ./pipe cmd1 cmd2\n");
        exit(1);
    }

    if (pipe(thepipe) == -1)
        oops("cannot get a pipe", 1);

    if ((pid = fork()) == -1)
        oops("cannot fork", 2);

    if (pid > 0)
    {
        close(thepipe[1]);

        if (dup2(thepipe[0], 0) == -1)
            oops("could not redirect stdin", 3);

        close(thepipe[0]);
        execlp(argv[2], argv[2], NULL);
        oops(argv[2], 4);
    }

    close(thepipe[0]);

    if (dup2(thepipe[1], 1) == -1)
        oops("could not redirect stdout", 4);

    close(thepipe[1]);
    execlp(argv[1], argv[1], NULL);
    oops(argv[1], 5);

    return 0;
}


I/O重定向和管道——《Unix/Linux编程实践教程》读书笔记(第10章)

I/O重定向和管道——《Unix/Linux编程实践教程》读书笔记(第10章)

1、I/O重定向的概念与原因 及 标准输入、输出的标准错误的定义

所以的Unix I/O重定向都基于标准数据流的原理。三个数据了分别如下:

    1)标准输入——需要处理的数据流

    2)标准输出——结果数据流

    3)标准错误输出——错误消息流


概念:所以的Unix工具都使用文件描述符0、1和2。标准输入文件的描述符是0,标准输出的文件描述符是1,而标准错误输出的文件描述符则是2。Unix假设文件描述符0、1、2已经被打开,可以分别进行读写操作。

通常通过shell命令行运行Unix系统工具时,stdin、stdout、stderr连接在终端上。因此,工具从键盘读取数据并且把输出和错误消息写到屏幕。

大部分的Unix工具处理从文件或标准输入读入的数据。如果在命令行上给出了文件名,工具将从文件读取数据。若无文件名,程序则从标准输入读取数据。从另一方面说,大多数程序并不接收输出文件名;它们总是将结果写到文件描述符1,并将错误消息写到文件描述符2。如果希望将进程的输出写道文件或另一个进程的输入去,就必须重定向相应的文件描述符。

重定向I/O的是shell而不是程序

最低可用文件描述符(lowest-available-fd)原则:文件描述符是一个数组的索引号。每个进程都有其打开的一组文件。这些打开的文件被保持在一个数组中。文件描述符即为某文件在此数组中的索引。当打开文件时,为此文件安排的描述符总是此数组中最低可用位置的索引。

将文件描述符0、1、2的概念和最低可用文件描述符原则结合使用,即可理解I/O重定向的工作原理


2、重定向标准I/O到文件

(1)如何将stdin定向到文件

a、close-then-open策略

close(0);
int fd = open(file, O_RDONLY);


b、open-close-dup-close策略
int oldfd = open(file, O_RDONLY);
#ifndef DUP2
    close(0);
    int newfd = dup(oldfd);
#else
    int newfd = dup2(oldfd, 0);
#endif
close(oldfd);


man 2 dup
#include <unistd.h>

int dup(int oldfd);
int dup2(int oldfd, int newfd);

系统调用dup复制了文件描述符oldfd。而dup2将oldfd文件描述符复制给newfd。两个文件描述符都指向同一个打开的文件。这两个调用都返回新的文件描述符,若发生错误,则返回-1。


c、open-dup2-close策略


(2)重定向到文件

共有3个基本的概念,利用它们是的Unix下的程序可以轻易地将标准输入、输出和错误信息输出连接到文件:

    a、标准输入、输出以及错误输出分别对应于文件描述符0、1、2;

    b、内核总是使用最低可用文件描述符;

    c、文件描述符集合通过exec调用传递,且不会被改变。

例子:

/*
 * who_to_file.c
 * purpose: show how to redirect output for another program
 * idea: fork, then in the child, redirect output, then exec
 */

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(void)
{
    pid_t   pid;
    int     fd;

    printf("about to run who into a file\n");

    /* create a new process or quit */
    if ((pid = fork()) == -1)
    {
        perror("fork");
        exit(1);
    }

    /* child does the work */
    if (pid == 0)
    {
        close(1);
        fd = creat("userlist", 0644);
        execlp("who", "who", NULL);
        perror("execlp");
        exit(1);
    }

    /* parent waits then reports */
    else
    {
        wait(NULL);
        printf("done running who. results in userlist\n");
    }

    return 0;
}


3、管道编程

(1)创建管道

man 2 pipe
#include <unistd.h>

int pipe(int pipefd[2]);

系统调用pipe创建管道并将两端连接到两个文件描述符。pipefd[0]为读数据端的文件描述符,而pipefd[1]则为写数据端的文件描述符。


(2)技术细节:管道并非文件

a、从管道中读数据

    管道读取阻塞:当进程试图从管道中读数据时,进程被挂起直到数据被写进管道。

    管道的读取结束标志:当所以的写操作关闭了管道的写数据端时,试图从管道读取数据的调用返回0,意味着文件的结束。

    多个读操作可能会引起麻烦:管道是一个队列。当进程从管道中读取数据之后,数据已经不存在了。

b、向管道中写数据

    写入数据阻塞直到管道有空间去容纳新的数据

    写入必须保证一个最小的块大小:POSIX标准规定内涵不会拆分小于512字节的块。而Linux则保证管道中可以存在4096字节的连续缓存。如果两个进程向管道写数据,并且没一个进程都限制其消息不打由于512字节,那么这些消息都不会被内核拆分。

    若无读操作在读数据,则写操作执行失败:如果所以的读操作都已将管道的读取端关闭,那么对管道的写入调用将会执行失败。如果在这种情况下,数据还可以被接收的话,为了避免数据丢失,内核采用了两种方法来通知进程:“此时的写操作是无意义的”。首先,内核发送SIGPIPE消息给进程。若进程被终止,则无任何事情发生。否则write调用返回-1,并且将errno置为EPIPE。

例子:

/*
 * pipe.c -
 *      demonstrates how to create a pipeline from one process to another
 * takes two args, each a command, and connectes
 * argv[1]s output to input of argv[2]
 * usage: pipe command1 command2
 * effect: command1 | command2
 * limitations: commands do not take arguments
 * users execlp() since known number of args
 * note: exchange child and parent and watch fun
 */

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

#define oops(m, x)  { perror(m); exit(x); }

int main(int argc, char **argv)
{
    int     thepipe[2],
            newfd,
            pid;

    if (argc != 3)
    {
        fprintf(stderr, "usage: ./pipe cmd1 cmd2\n");
        exit(1);
    }

    if (pipe(thepipe) == -1)
        oops("cannot get a pipe", 1);

    if ((pid = fork()) == -1)
        oops("cannot fork", 2);

    if (pid > 0)
    {
        close(thepipe[1]);

        if (dup2(thepipe[0], 0) == -1)
            oops("could not redirect stdin", 3);

        close(thepipe[0]);
        execlp(argv[2], argv[2], NULL);
        oops(argv[2], 4);
    }

    close(thepipe[0]);

    if (dup2(thepipe[1], 1) == -1)
        oops("could not redirect stdout", 4);

    close(thepipe[1]);
    execlp(argv[1], argv[1], NULL);
    oops(argv[1], 5);

    return 0;
}


Linux vs Unix - Linux与Unix到底的不同

Linux vs Unix - Linux与Unix到底的不同

Linux和Unix这两个术语可以互换地用来指同一操作系统。这在很大程度上是由于他们惊人的相似之处,以致很多人不能区分这两者。在Linux vs Unix难题中,存在关于哪个系统做什么的困惑。如果您出生于90年代中期,那么您很可能只与Linux操作系统进行过交互。Linux在数据中心和云计算平台中占据着巨大的市场份额。Linux无处不在,它支撑着智能手机、Android TV和物联网设备等大多数智能设备。 Linux教程 虽然Linux和Unix确实有很多共同点,尤其是在文件系统层次结构和终端命令方面,但我们不能忽略这两个系统之间存在的差异。在本文中,我们将更详细地了解Unix和Linux,并详细说明两者之间的差异。

首先,Linux是Unix的克隆。它是一种Unix变体,飞速发展,产生了数百种风格或发行版。它们由一个充满活力的开发人员社区维护。为了更好地理解我们是如何走到今天这一步的,让我们回顾一下Unix的历史。稍后,我们将研究引发Linux创建的一系列事件。

Unix的历史

Unix可以追溯到20世纪60年代末,在AT&T的贝尔实验室,当时由Dennis Ritchie和Ken Thompson领导的一群雄心勃勃的开发人员正在寻求为称为PDP-7的小型计算机开发多用户多任务系统。当时,Unix是Multics操作系统(Multiplexed Information and Computing Service)的派生产品。这是为大型机提供支持的系统。

然而,到了20世纪70年代,这两位主要开发人员开始对UNIX的发展方向感到不安。由于对Multics的范围和方向感到失望,他们决定制定一个不同的路线,从Multics衍生出一个新的操作系统。在被认为是C语言之父的Dennis Ritchie和Go语言的发明者Ken Thompson的共同努力下,诞生了一个更好的系统,即后来的UNIX。UNIX被证明是可移植的,可以被许多硬件体系结构安装和支持。

Unix在70年代和80年代迅速发展,并在学术界流行起来。在采纳并改变Unix发展轨迹的机构中,加利福尼亚大学伯克利分校(University of California in Berkley)的工程师们对Unix进行了进一步的修改和开发,从而产生了一种名为BSD的新系统,即BSD软件开发(Berkeley Software Development)的缩写。BSD附带了一些增强功能和新的软件应用程序,预示着操作系统的一个新时代。与此同时,AT&T制定了自己的路线,并推出了自己的UNIX版本,即System V。后来BSD出现了,并很快取代了System V,从BSD衍生出了NetBSD、OpenBSD和FreeBSD等变种。

Linux的诞生

1990年,Linux之父Linus Torvalds进一步研究了UNIX,并最终提出了一个可行的Linux内核,他称之为Linux。内核为实现带有实用工具和其他应用程序的操作系统打开了大门,远离了专有的UNIX系统。随着时间的推移,Linux在GNU/GPL许可模型下成为开放源码和免费使用的工具。这就为其他发行版腾出了空间,比如带有Linux内核的Slackware,像GCC编译器这样的GNU工具,X windows系统(图形用户界面),以及其他BSD组件。

现在已经有成百上千的Linux发行版。其中最流行和广泛使用的发行版是Ubuntu、Linux Mint、Fedora、Debian、CentOS、Arch Linux和Manjaro。

到目前为止,我们已经了解了UNIX的简短历史,以及通过许多开发人员的共同努力,它是如何产生了Linux这个免费和开源的系统。问题是,UNIX和Linux之间有什么区别?UNIX中有什么是Linux中没有的?

现在让我们换下角度,把焦点放在这两者的区别上:

Linux vs UNIX

现在让我们看看这两种操作系统之间的区别。

首先,Unix是一种最初由AT&T贝尔实验室开发的操作系统。Linux及其派生产品就是从Unix派生出来的。Linux代码是由Linux Torvalds在1991年从头开始开发的。

Linux是免费下载和使用的。虽然一些企业发行版(如RHEL)需要付费订阅,但大多数发行版在很大程度上仍然是免费和开源的。这是使它如此受欢迎并在开发人员和软件工程师中广泛使用的一个特性。它主要解释了为什么我们有无数的Linux发行版,每个发行版都有自己独特的方式。另一方面,UNIX在很大程度上是专有的,通常预装在大多数硬件中,macOS就是一个很好的例子。

此外,虽然Linux是开源的,但UNIX不是。您需要它的制造商的许可,即使这样,您也不能查看、修改代码,甚至不能重新发布代码。在Linux中,情况就完全不同了。Linux是免费和开放源码的,它允许用户自由地修改代码和重新发布代码而不受任何限制。

由于它的成本效益,Linux在数据中心、云托管平台,甚至在家庭或办公室的桌面使用上比UNIX更受欢迎。UNIX是专有的,一直是专门为应用程序服务器和internet服务器保留的。随着时间的推移,UNIX的使用量逐渐减少,Linux在云托管平台中占据了领先地位。

就可移植性而言,Linux的可移植性非常好,几乎可以安装在任何硬件平台上。你可以把它安装在intel, AMD处理器的硬件上,甚至是ARM的设备上,比如Raspberry Pi。与之形成鲜明对比的是,UNIX只能在少数几个平台上安装。

支持呢?

Linux构成了一个由活跃的开源爱好者组成的广泛社区。此外,还有大量的论坛为Linux用户提供支持和指导。然而,与Linux不同,UNIX中的支持是商业的。

总结

在本文中,我们将阐明UNIX的历史,以及开发人员如何通过各种努力将Linux开发成一种免费和开放源码的系统。最后,我们讨论了UNIX和Linux之间的差异,并详细说明了其中的细微差别。

Linux在开放源码领域占据着主导地位,它拥有大量可以免费下载和使用的发行版。虽然仍然在特殊平台中使用,但UNIX的使用和需求正在下降。这主要是由于供应商锁定和专有许可。

以上就是良许教程网为各位朋友分享的Linux vs Unix - Linux与Unix到底的不同。 以上就是良许教程网为各位朋友分享的Linux相关知识。

linux – 从windows转移到* nix编程平台

linux – 从windows转移到* nix编程平台

如何在 Windows上花费超过10年后迁移到* nix平台?哪种口味易于处理,让我更舒服,然后我可以切换到更多stadard * nix口味?
我现在已经推迟了一段时间.帮助我额外推动.

解决方法

Linux是最易于访问且具有最成熟的桌面功能. BSD( in its various flavours)具有较少的用户空间行李,并且在基础层面上更容易理解.在这方面,它更像是传统的Unix而不是现代的Linux发行版.有些人可能会认为这是一件好事(并且从某些角度来看),但对熟悉Windows的人来说会更加陌生.

主要的桌面发行版是Ubuntu和Fedora.这些都是功能强大的系统,但在用户空间体系结构上有所不同桌面环境的工具和系统安全的默认配置在Ubuntu上的工作方式与在大多数其他Linux或Unix版本上的工作方式略有不同但这个与发展无关.从用户的角度来看,这些都是一个良好的开端.

从开发人员的角度来看,Unix和Linux的所有现代风格都非常相似,并且基本上共享相同的开发人员工具链.如果您想从程序员的角度了解系统,那么选择起来相对较少.

大多数unix编程都可以通过程序员的编辑器(例如vim或emacs,)非常有效地完成,这两种编辑器都有文本模式和窗口风格.这些编辑器非常强大,并且具有相当古怪的用户界面 – 用户界面是常用的,但却极大地促进了工具的强大功能.如果您对这些工具不满意,this posting讨论了几种其他编辑器,这些编辑器提供了更接近常见Windows工具的用户体验.

有一些IDE,例如Eclipse,可能对Windows / Visual Studio上的人更感兴趣.

Stackoverflow上讨论linux / unix资源的一些帖子是:

> What are good linux-unix books for an advancing user
> What are some good resources for learning C beyond K&R
> Resources for learning C program design

如果你有时间并想要真正参观螺母和螺栓Linux From Scratch是一个教程,通过手工构建Linux安装.这是一个深入学习的好方法.

对于编程,请了解K& R中的C / unix以及上面链接的问题中提到的一些资源.相当于Unix世界中的Petzold,Prosise和Richter是W Richard Stevens的Advanced Programming in the Unix Environment和Unix Network Programming vol. 1 and 2.

学习Perl或Python等动态语言之一,如果您还不熟悉这些语言,也是很有用的.作为奖励,你可以从Activestate获得上述两个好的Windows端口,这意味着这些技能在两个平台上都很有用.

如果您正在使用C,请查看QT.这可以说是市场上最好的跨平台GUI工具包,并且(再次)具有可转移回Windows的技能集和工具链的优势.关于这个问题还有several good books(作为奖励)它也是works well with Python.

最后,Cygwin是一个在Windows上运行的unix仿真层,它提供了基本类似unix的环境.在架构上,Cygwin是glibc的一个端口,而crt(GNU工具链的基础库)作为Win32之上的适配器.这个仿真层可以很容易地将unix / linux应用程序移植到Cygwin上.该平台附带了一套完整的软件 – 本质上是一个托管在Windows内核上的完整Linux发行版.它允许您在Windows上以类似unix的方式工作,而无需维护单独的操作系统安装.如果您不想运行VM,多个启动或多台PC,它可能是一种简化为unix的方法.

关于Unix/Linux编程实践教程–od在OS X的实现linux中od命令的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于I/O 重定向和管道 ——《Unix/Linux 编程实践教程》读书笔记(第 10 章)、I/O重定向和管道——《Unix/Linux编程实践教程》读书笔记(第10章)、Linux vs Unix - Linux与Unix到底的不同、linux – 从windows转移到* nix编程平台的相关信息,请在本站寻找。

本文标签: