精华内容
下载资源
问答
  • 展开全部如果你要获取的是Internet时间,可以使用NTP服务。NTP概念简介Network Time Protocol(NTP)是62616964757a686964616fe4b893e5b19e31333332643164用来使计算机时间同步化一种协议,它可以使计算机对其服务器...

    展开全部

    如果你要获取的是Internet时间,可以使用NTP服务。

    NTP概念简介

    Network Time Protocol(NTP)是62616964757a686964616fe4b893e5b19e31333332643164用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高精准度的时间校正(LAN上与标准间差小于1毫秒,WAN上几十毫秒),且可介由加密确认的方式来防止恶毒的协议攻击。

    java实现:import java.io.InputStream;

    import java.net.Socket;

    public class TimeUtil {

    public static final int DEFAULT_PORT = 37;//NTP服务器端口

    public static final String DEFAULT_HOST = "time-nw.nist.gov";//NTP服务器地址

    private TimeUtil() {

    };

    public static long currentTimeMillis(Boolean sync) {

    if (sync != null && sync.booleanValue() != true)

    return System.currentTimeMillis();

    try {

    return syncCurrentTime();

    } catch (Exception e) {

    return System.currentTimeMillis();

    }

    }

    public static long syncCurrentTime()  throws Exception {

    // The time protocol sets the epoch at 1900,

    // the java Date class at 1970. This number

    // converts between them.

    long differenceBetweenEpochs = 2208988800L;

    // If you'd rather not use the magic number uncomment

    // the following section which calculates it directly.

    /*

    * TimeZone gmt = TimeZone.getTimeZone("GMT"); Calendar epoch1900 =

    * Calendar.getInstance(gmt); epoch1900.set(1900, 01, 01, 00, 00, 00);

    * long epoch1900ms = epoch1900.getTime().getTime(); Calendar epoch1970

    * = Calendar.getInstance(gmt); epoch1970.set(1970, 01, 01, 00, 00, 00);

    * long epoch1970ms = epoch1970.getTime().getTime();

    *

    * long differenceInMS = epoch1970ms - epoch1900ms; long

    * differenceBetweenEpochs = differenceInMS/1000;

    */

    InputStream raw = null;

    try {

    Socket theSocket = new Socket(DEFAULT_HOST, DEFAULT_PORT);

    raw = theSocket.getInputStream();

    long secondsSince1900 = 0;

    for (int i = 0; i 

    secondsSince1900 = (secondsSince1900 <

    }

    if (raw != null)

    raw.close();

    long secondsSince1970 = secondsSince1900 - differenceBetweenEpochs;

    long msSince1970 = secondsSince1970 * 1000;

    return msSince1970;

    } catch (Exception e) {

    throw new Exception(e);

    }

    }

    }

    中国大概能用的NTP时间服务器

    server 133.100.11.8 prefer

    server 210.72.145.44

    server 203.117.180.36 //程序中所用的

    server 131.107.1.10

    server time.asia.apple.com

    server 64.236.96.53

    server 130.149.17.21

    server 66.92.68.246

    server www.freebsd.org

    server 18.145.0.30

    server clock.via.net

    server 137.92.140.80

    server 133.100.9.2

    server 128.118.46.3

    server ntp.nasa.gov

    server 129.7.1.66

    server ntp-sop.inria.frserver 210.72.145.44(国家授时中心服务器IP地址)

    ntpdate 131.107.1.10

    ntpdate -s time.asia.apple.com

    展开全文
  • 作为一种成功网络编程语言,Java为用户提供了十分完善网络功能,比如获取网络上各种资源,与服务器建立连接和通信,传递本地数据等,所有这些有关功能都定义在java.net包中,比如在载入声音或者图片时候,...

    TCP/IP,传输控制协议/网间协议是Internet的主要协议,它定义了计算机和外设进行通信所使用的规则。作为一种成功的网络编程语言,Java为用户提供了十分完善的网络功能,比如获取网络上的各种资源,与服务器建立连接和通信,传递本地数据等,所有这些有关的功能都定义在java.net包中,比如在载入声音或者图片的时候,只要指定了数据的URL地址,就能够利用getAudioClip()和getImage()实现,这种方式是Java网络通信功能中最高级也是最简单的一种。

    针对网络通信的不同层次,Java所能提供的网络功能按层次以及使用方法分为四大类: InetAddress,URL,Socket,Datagram。

    InetAddress面向的是IP层,用于标识网络上的硬件资源。

    URL面向应用层,可以通过URL的网络资源表达形式确定数据在网络中的位置,利用URL对象中提供的相关方法,直接读入网络中的数据,或者将本地数据传送到网络的另一端。

    Socket面向传输层,使用的是TCP协议,Socket是指两个程序在网络上的通信连接,由于在TCP/IP协议下的客户/服务器软件通常使用Socket来进行信息交流,因此这种方法也是传统网络程序所经常用到的一种方式。

    Datagram也面向传输层,使用的是UDP协议,是另一种网络传输方式,它把数据的目的地记录在数据包中,然后直接放在网络上。

    使用InetAddress:

    类InetAddress可以用于标识网络上的硬件资源,它提供了一系列的方法,用来描述,获取及使用网络资源。

    InetAddress类没有构造函数,因此不能用new来构造一个InetAddress实例。通常是用它提供的静态方法来获取:

    public static InetAddress getByName(String host);

    其中,host可以是一台机器名,也可以是一个形如“%d.%d.%d.%d”的IP地址或一个DSN域名。另外两种方式为:

    public static InetAddress getLocalHost();

    public static InetAddress[] getAllByName(String host);

    这三个方法通常会产生UnknownHostException异常,应在程序中捕获处理。下面是InetAddress类的几个主要方法,通过上述方法获得InetAddress类的实例后就可以使用。

    public byte[] getAddress()–获得本对象的IP地址(存放在字节数组中);

    public String getHostAddress()–获得本对象的IP地址 “%d.%d.%d.%d”

    public String getHostName()–获得本对象的机器名。

    接下来演示Java如何根据域名自动到DNS(域名服务)上查找IP地址,其中与DNS服务器的连接只有一行代码。

    package javaapplication24;

    /**

    *

    * @author mjd

    */

    import java.net.*;

    public class GetIp {

    /**

    * @param args the command line arguments

    */

    public static void main(String[] args) {

    // TODO code application logic here

    InetAddress hd = null;

    try{

    hd = InetAddress.getByName(“www.sau.edu.cn”);

    }catch(UnknownHostException e){}

    System.out.println(hd);

    }

    }

    136be34314a57ba454d97dfa8ef5d707.png

    执行GetIP后,可以得到该地址信息。

    通过InetAddress,可以获取本机的IP地址:

    package getlocalhost;

    /**

    *

    * @author mjd

    */

    import java.net.*;

    public class GetLocalHost {

    /**

    * @param args the command line arguments

    */

    public static void main(String[] args) {

    // TODO code application logic here

    InetAddress myIP = null;

    try{

    myIP = InetAddress.getLocalHost();

    }catch(UnknownHostException e){}

    System.out.println(myIP);

    }

    }

    136be34314a57ba454d97dfa8ef5d707.png

    可以得到本机的IP地址。

    展开全文
  • java源码包---java 源码 大量 实例

    千次下载 热门讨论 2013-04-18 23:15:26
    2个目标文件,FTP目标是:(1)提高文件共享性(计算机程序和/或数据),(2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间文件存储系统导致变化,(4)为了可靠和高效地传输,虽然用户...
  • 0 引 言  在信息化社会发展过程中,计算机网络应用逐渐渗透到各个工程技术领域和社会生活方方面面。资源共享、文件传输等技术在...Java不仅具有很好安全性和可移植性,还为Internet编程提供了丰富网络类库支持
  • 一、场景:复制粘贴文件,把一组数据... (打印文件等等)输入流: 文件输入-读取文件当中的内容文件输出-写入文件File类的使用:如何使用java jdk提供的api来进行文件的创建,目录的创建,以及获取文件和目录的一些属...

    一、场景:

    复制粘贴文件,把一组数据存储到计算机的过程。

    更改论坛qq微信头像,上传头像从本地上传到了网络服务器上。

    这些问题的解决肯定需要输入输出流的。

    输出流:

    d54160271ad9ea6f59f1434ff6d9bd21.png

    流就是指一连串流动的字符,以先进先出的方式发送信息的通道。 (打印文件等等)

    输入流:

    ac04fdaec7320952287821b3d761cc22.png

    文件输入-读取文件当中的内容

    文件输出-写入文件

    File类的使用:如何使用java jdk提供的api来进行文件的创建,目录的创建,以及获取文件和目录的一些属性。这些类型都是使用file类来完成的。

    分为字节流(二进制字符数据010100111这种的)和字符流 (anc*&%^类型的字符)

    对象的序列化和反序列化

    二、File类

    什么是文件?文件可认为是相关记录或放在一起的数据的集合。在java当中使用java.io.file类对文件进行操作。

    创建文件,创建目录的各种api

    package com.immoc.file;

    import java.io.File;

    import java.io.IOException;

    public class FileDemo {

    public static void main(String[] args) {

    // 创建File对象

    //①

    //File file = new File("/Users/dongwenjie/Desktop/git.sh");

    //②

    //File file = new File("/Users/dongwenjie","/Desktop/git.sh");

    //③

    //File file = new File("/Users/dongwenjie");

    //File file1 = new File(file, "/Desktop/git.sh");

    //System.out.println(file);

    //System.out.println(file1);

    判断是文件还是目录

    //System.out.println("是否是目录:" + file.isDirectory());

    //System.out.println("是否是文件:" + file.isFile());

    // 创建单个文件夹

    //File file = new File("/Users/dongwenjie/Desktop/","demohahaha");

    //if(!file.exists()) {

    //file.mkdir();

    //}

    //

    //

    创建多个带层级的文件夹

    //File file1 = new File("/Users/dongwenjie/Desktop/demo1/demo2");

    //if(!file1.exists()) {

    //file1.mkdirs();

    //}

    // 创建文件

    File file2 = new File("/Users/dongwenjie/Desktop/demo1.txt");

    if(!file2.exists()) {

    try {

    file2.createNewFile();

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }

    }

    三、字节流

    字节输入流InputStream

    字节输出流OutputStream

    193b5b512944fbe40898045c35fbb1f2.png

    d32e138fa99df0b32942de8d528f162b.png

    FileInputStream

    从文件系统中的某个文件中获得输入字节。

    用于读取诸如图像数据之类的原始字节流。

    35dacbf375b70fb34418af1b67e85fc3.png

    0ce988a6afbf67f0a0e3facd64dd081c.png

    如果返回值为-1的话,代表已经读到了文件的末尾。

    四、读取单个英文字符。

    package com.immoc.file;

    import java.io.FileInputStream;

    import java.io.FileNotFoundException;

    import java.io.IOException;

    public class FIleInputStreamDemo {

    public static void main(String[] args) {

    // 创建一个FileInputStream对象

    try {

    FileInputStream f1 = new FileInputStream("tianjia.txt");

    int n = f1.read();

    System.out.println(n);

    System.out.println((char)n);

    f1.close();

    } catch (FileNotFoundException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }

    五、循环打印文件字符

    package com.immoc.file;

    import java.io.FileInputStream;

    import java.io.FileNotFoundException;

    import java.io.IOException;

    public class FIleInputStreamDemo {

    public static void main(String[] args) {

    // 创建一个FileInputStream对象

    try {

    FileInputStream f1 = new FileInputStream("tianjia.txt");

    int n = f1.read();

    while (n != -1) {

    System.out.println((char)n);

    n = f1.read();

    }

    //System.out.println(n);

    //System.out.println((char)n);

    f1.close();

    } catch (FileNotFoundException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }

    六、简单的读取文件内容

    package com.immoc.file;

    import java.io.FileInputStream;

    import java.io.FileNotFoundException;

    import java.io.IOException;

    public class FileInputStreamDemo2 {

    public static void main(String[] args) {

    // 创建一个FileInputStream对象

    try {

    FileInputStream f1 = new FileInputStream("tianjia.txt");

    byte[] b = new byte[100];

    f1.read(b);

    System.out.println(b);

    System.out.println(new String(b)); // ABCD我爱我老妈

    f1.close();

    } catch (FileNotFoundException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }

    七、文件拷贝

    package com.immoc.file;

    import java.io.FileInputStream;

    import java.io.FileNotFoundException;

    import java.io.FileOutputStream;

    import java.io.IOException;

    import org.omg.CORBA.TypeCodeHolder;

    public class FileOutputDemo01 {

    public static void main(String[] args) {

    // 文件拷贝

    try {

    FileInputStream f1 = new FileInputStream("components.jpeg");

    FileOutputStream f2 = new FileOutputStream("componentscopy.jpeg");

    int n = 0;

    byte[] b = new byte[1024];

    while((n=f1.read(b))!=-1) {

    f2.write(b,0,n);

    }

    f1.close();

    f2.close();

    } catch (FileNotFoundException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    }

    八:缓冲流

    缓冲输入流BufferedInputStream

    缓冲输出流BufferedOutputStream

    之前的api都是从硬盘中读出数据的,这样的读取速度是比较慢的,远没有从内存当中读取数据更快,所以使用了缓冲的输入输出流就能提高读写速度。

    缓冲输入流是不能直接读取文件当中的数据的,是需要和文件输入流结合。

    加入了缓冲输入流读取文件的过程:

    ①FileInputStream将数据源从文件中读取出来。

    ②通过缓冲流最后读入到字节数组当中,而被程序所读取到。

    写文件反之。

    缓冲区满了自动执行写操作,缓冲区不慢进行强制清空。

    package com.immoc.file;

    import java.io.BufferedInputStream;

    import java.io.BufferedOutputStream;

    import java.io.FileInputStream;

    import java.io.FileNotFoundException;

    import java.io.FileOutputStream;

    import java.io.IOException;

    public class BufferDemo {

    public static void main(String[] args) {

    try {

    FileOutputStream fos = new FileOutputStream("tianjia.txt");

    BufferedOutputStream bos = new BufferedOutputStream(fos);

    FileInputStream fis = new FileInputStream("tianjia.txt");

    BufferedInputStream bis = new BufferedInputStream(fis);

    System.out.println(System.currentTimeMillis());

    bos.write(50);

    bos.write('a');

    // flush和close方法都可以强制清空缓冲区里面的数据

    bos.flush();

    System.out.println(bis.read());

    System.out.println((char)bis.read());

    System.out.println(System.currentTimeMillis());

    fos.close();

    bos.close();

    fis.close();

    bis.close();

    } catch (FileNotFoundException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    }

    九、字符流

    字符输入流Reader

    字符输出流Writer

    26857937ba7abb8ddfe0aec005dd8f15.png

    十、字节字符转换流

    InputStreamReader

    OutputStreamReader

    十一、字符输出流

    package com.immoc.file;

    import java.io.FileInputStream;

    import java.io.FileNotFoundException;

    import java.io.IOException;

    import java.io.InputStreamReader;

    public class ReaderDemo {

    public static void main(String[] args) {

    try {

    FileInputStream fis = new FileInputStream("tianjia.txt");

    InputStreamReader isr = new InputStreamReader(fis);

    int n = 0;

    char[] cbuf = new char[100];

    while((n=isr.read(cbuf))!=-1) {

    String s = new String(cbuf,0,n);

    System.out.println(s);

    }

    } catch (FileNotFoundException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    }

    十二,字符输入流,写入一个新文件

    package com.immoc.file;

    import java.io.FileInputStream;

    import java.io.FileNotFoundException;

    import java.io.FileOutputStream;

    import java.io.IOException;

    import java.io.InputStreamReader;

    import java.io.OutputStreamWriter;

    public class ReaderDemo {

    public static void main(String[] args) {

    try {

    FileInputStream fis = new FileInputStream("tianjia.txt");

    InputStreamReader isr = new InputStreamReader(fis);

    FileOutputStream fos = new FileOutputStream("tianjia1.txt");

    OutputStreamWriter osw = new OutputStreamWriter(fos);

    int n = 0;

    char[] cbuf = new char[100];

    while((n=isr.read(cbuf))!=-1) {

    osw.write(cbuf,0,n);

    osw.flush();

    }

    fis.close();

    fos.close();

    isr.close();

    osw.close();

    } catch (FileNotFoundException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    }

    读写数据的时候一定要保持编码的一致,这样才不会出现乱码问题。

    十三、对象序列化

    序列化:把Java对象转换成字节序列的过程。

    反序列化:把字节序列恢复为Java对象的过程。

    package com.immoc.Goods;

    import java.io.FileInputStream;

    import java.io.FileNotFoundException;

    import java.io.FileOutputStream;

    import java.io.IOException;

    import java.io.ObjectInputStream;

    import java.io.ObjectOutputStream;

    public class GoodsTest {

    public static void main(String[] args) {

    // TODO Auto-generated method stub

    Goods goods1 = new Goods("gd001", "电脑", 3000);

    try {

    FileOutputStream fos = new FileOutputStream("tianjia.txt");

    ObjectOutputStream oos = new ObjectOutputStream(fos);

    FileInputStream fis = new FileInputStream("tianjia.txt");

    ObjectInputStream ois = new ObjectInputStream(fis);

    // 将Goods对象信息写入文件

    oos.writeObject(goods1);

    oos.flush();

    // 读对象信息

    try {

    Goods goods = (Goods)ois.readObject();

    System.out.println(goods);

    } catch (ClassNotFoundException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    fos.close();

    oos.close();

    } catch (FileNotFoundException e) {

    // TODO: handle exception

    } catch( IOException e) {

    e.printStackTrace();

    }

    }

    }

    十四:

    流的概念

    File类的使用

    字节流

    字符流

    对象的序列化和反序列化

    展开全文
  • 一个用Java编写设备I / O库,它为连接到Raspberry Pi等单板计算机的GPIO / I2C / SPI设备(LED,按钮,传感器,电机,显示器等)提供面向对象接口。 实际GPIO / I2C / SPI设备通信委托给可插拔服务提供商,以...
  • 操作系统(operating system)的功能操作系统的任务是在多个程序之间共享一台计算机,并提供比单独的硬件所支持的更为有用的服务集。操作系统管理和抽象化低级硬件,因此,例如,文字处理器不必担心自己正在使用哪种...

    操作系统

    操作系统接口

    前言

    实验1需要我们调用unix操作系统保持出的接口,因此首先需要了解unix操作系统有关的知识。

    操作系统(operating system)的功能

    • 操作系统的任务是在多个程序之间共享一台计算机,并提供比单独的硬件所支持的更为有用的服务集。
    • 操作系统管理和抽象化低级硬件,因此,例如,文字处理器不必担心自己正在使用哪种类型的硬件。
    • 操作系统允许多个程序之间共享硬件,以便它们可以并发运行。
    • 最后,操作系统提供了程序交互的方式,以便它们可以共享数据,协同工作。
    • 操作系统为用户程序提供接口去调用。设计一个好的接口操作系统接口非常困难。
    • 一方面希望简单,一方面又希望实现复杂的功能。
    • 一种好的设计思路是接口之间可以通过某种机制组合起来以实现复杂的操作。
    • 本实验中,使用了xv6 操作系统。其提供了unix的基本操作系统接口,并且模仿了Unix的内部设计。
    • unix提供的接口很少,但是由于其可以组合的机制,提供了难以想象的通用性。该接口非常成功,以至于现代操作系统(BSD,Linux,Mac OS X,Solaris,甚至在较小程度上是Microsoft Windows)都具有类似Unix的接口。了解xv6是了解这些系统和许多其他系统的良好起点。
    • 内核是操作系统的核心,为运行的程序提供服务。 每个正在运行的程序(称为进程)都具有包含指令,数据和堆栈的内存。
    • 指令说明了程序的运行逻辑。数据是指令运行所需要的变量。堆栈组织程序的过程调用。
    • 当进程需要调用内核服务时,它将通过操作系统提供的接口进行过程调用。 这样的过程称为系统调用。
    • 内核使用CPU的硬件保护机制来确保在用户空间中执行的每个进程只能访问其自己的内存。
    • 用户程序调用操作系统接口后,硬件提高权限级别,并开始在内核中执行预先安排的功能。
    • shell是一个普通程序,可读取用户命令并执行命令。 shell是用户程序而不是内核的一部分,这一事实说明了操作系统接口的强大功能。shell没有什么特别之处,这也意味着shell易于更换;现代Unix系统有多种shell可供选择,每种shell都有其自己的用户界面和脚本功能。 xv6 shell是Unix Bourne shell的简单实现。 可以在(user / sh.c:1)中找到其实现。

    操作系统接口

    • xv6进程由用户空间内存(指令,数据和堆栈)和内核专有的每个进程状态组成。
    • xv6保证进程的并发执行,在多个进程之间切换CPU能力。
    • 当某个进程未执行时,xv6保存其CPU寄存器,并在下次运行该进程时恢复它们。 内核将进程标识符或pid与每个进程相关联。
    • 进程可以使用fork系统调用来创建新进程。 Fork创建一个称为子进程的新进程,该进程与父进程的内存完全相同。
    • Fork在子进程与父进程中都会返回。
    • 在父进程中,fork返回子进程的pid; 在子进程中,它返回零。
      例如,考虑以下用C编程语言编写的程序片段:
    int pid = fork();
    if(pid > 0){
        printf("parent: child=%den", pid);
        pid = wait(0);
        printf("child %d is doneen", pid);
    } else if(pid == 0){
        printf("child: exitingen");
        exit(0);
    } else {
        printf("fork erroren");
    }
    
    • exit导致调用进程停止执行并释放资源,例如内存和打开的文件。
    • exit接受一个整数状态参数,通常0表示成功,1表示失败。
    • wait系统调用返回当前进程已退出子进程的pid,并将该子进程的退出状态传递给wait。
    • 如果子进程都没有退出,一直会等待。
    • 如果父进程不在乎子进程的退出状态,则可以传递状态0。

    在下面的例子中,输出是:

    • parent: child=1234
    • child: exiting

    也可能出现另外的情况,具体取决于父进程还是子进程首先进入其printf调用。

    • 子进程退出后,父进程的wait返回,导致父进程打印出:
    • parent: child 1234 is done。
    • 尽管子进程最初具有与父进程相同的内存内容,但是父进程和子进程执行时使用的是不同的内存和不同的寄存器。
    • 更改一个变量不会影响另一个变量。
    • 例如,当wait的返回值在父进程中存储到pid中时,它不会更改子进程中的pid。 子进程中的pid的值仍为零。
    • exec系统调用使用从文件系统中存储的文件加载的新的内存映像替换调用进程的内存。
    • 该文件必须具有特定的格式,该格式指定文件的哪一部分包含指令,哪一部分是数据,从哪条指令开始等。
    • xv6使用ELF格式,第3章将对此进行详细讨论。
    • 当exec成功执行时,它不会返回到调用程序。从文件加载的指令在ELF标头中声明的入口点开始执行。
    • Exec接受两个参数:包含可执行文件的文件名和一个字符串参数数组。 例如:
    char *argv[3];
    argv[0] = "echo";
    argv[1] = "hello";
    argv[2] = 0;
    exec("/bin/echo", argv);
    printf("exec erroren");
    

    该片段将调用程序以程序/ bin / echo的实例替换,参数列表为echo hello。 大多数程序会忽略第一个参数,这通常是程序的名称

    • xv6 Shell使用上述调用执行用户运行的程序。
    • xv6 Shell使用上述调用代表用户运行程序。
    • shell的主要结构很简单; 参见main(user / sh.c:145)。
    • 主循环使用getcmd从用户读取一行输入。 然后,它将调用fork,这将创建shell进程的副本。
    • 父进程调用wait,而子进程运行命令。 例如,如果用户键入“ echo hello”给shell,则将以“ echo hello”作为参数调用runcmd。 runcmd(user / sh.c:58)运行实际命令
    • 对于“ echo hello”,它将调用exec(user / sh.c:78)
    • 如果exec成功,则子进程将从echo执行指令,而不是runcmd。
    • 在某些时候,echo将调用exit,这将导致父进程从main(user / sh.c:145)的wait中返回。
    • 您可能想知道为什么fork和exec不能在单个调用中组合? 稍后我们将看到,用于创建进程和加载程序的单独调用在Shell中用于I / O重定向的用法很巧妙。
    • 为了避免创建重复进程然后立即替换它的浪费,运行中的内核通过使用虚拟内存技术(如copy-on-write 写时复制)来针对此用例优化fork的实现。
    • Xv6隐式分配了大多数用户空间内存:fork分配了子进程复制父进程所需的内存,而exec分配了足够的内存来保存可执行文件。
    • 一个在运行时需要更多内存的进程(可能是malloc)可以调用sbrk(n)将其数据内存增加n个字节。 sbrk返回新内存的位置。
    • Xv6没有提供用户概念来保护一个用户免受另一个用户侵害;用Unix术语,所有xv6进程都以root身份运行。

    I/O 与文件描述符

    * 文件描述符是一个小的整数,表示进程可以从中读取或写入的内核管理的对象。 进程可以通过打开文件,目录或设备,或通过创建管道,或通过复制现有描述符来获取文件描述符。 为简单起见,我们通常将文件描述符所指的对象称为“文件”; 文件描述符接口抽象了文件,管道和设备之间的差异,使它们看起来都像字节流。
    * 在内部,xv6内核使用文件描述符作为每个进程表的索引,因此每个进程都有一个从零开始的文件描述符专用空间。 按照惯例,进程从文件描述符0(标准输入)读取,将输出写入文件描述符1(标准输出),并将错误消息写入文件描述符2(标准错误)。 就像我们将看到的那样,shell利用约定来实现I / O重定向(redirection)和管道(pipelines)。 shell确保始终打开三个文件描述符(user / sh.c:151),默认情况下,这三个文件描述符是控制台(console)的文件描述符。
    
    • read系统调用从文件描述符读取字节。
    • write系统调用从文件描述符写入字节。
    • 调用read(fd,buf,n)最多从文件描述符fd中读取n个字节,将它们复制到buf中,并返回读取的字节数。 引用文件的每个文件描述符都有一个与之关联的偏移量。read从当前文件偏移量读取数据,随着读取到的数据增加,文件的偏移量随之增加。当没有更多字节可以读取时,read将返回零以指示文件末尾。
    • 调用write(fd,buf,n)将buf中的n个字节写入文件描述符fd,并返回写入的字节数。 仅在发生错误时才写入少于n个字节。 与读操作类似,写操作会在当前文件偏移量处写入数据,然后将偏移量增加写入的字节数:每次写操作都从上次中止的位置开始。
    • 以下程序片段(cat命令的功能)将数据从其标准输入复制到其标准输出。 如果发生错误,它将向标准错误写入一条消息。
    char buf[512];
    int n;
    for(;;){
        n = read(0, buf, sizeof buf);
        if(n == 0)
        break;
        if(n < 0){
            fprintf(2, "read erroren");
            exit();
        }
        if(write(1, buf, n) != n){
            fprintf(2, "write erroren");
            exit();
        }
    }
    
    在代码片段中要注意的重要一点是cat不知道它是从文件,控制台还是管道中读取。 同样,cat不知道它是要打印到控制台,文件还是其他地方。 使用文件描述符以及文件描述符0是标准输入和输出文件描述符是标准输出的约定可以实现cat的简单实现。close系统调用将释放文件描述符,以供将来的open,pipe或dup系统调用重用。 新分配的文件描述符始终是当前进程中编号最小的未使用的描述符。
    

    文件描述符和fork交互使I/O重定向易于实现。Fork会复制父文件的文件描述符表及其内存,以便子文件与父文件打开完全相同的文件。 exec系统调用替换了调用进程的内存,但保留了其文件表。 此行为允许Shell通过分叉,重新打开选定的文件描述符,然后exec新程序来实现I / O重定向。 这是shell为cat <input.txt命令运行的代码的简化版本:

    char *argv[2];
        argv[0] = "cat";
        argv[1] = 0;
        if(fork() == 0) {
            close(0);
            open("input.txt", O_RDONLY);
            exec("cat", argv);
        }
    
    • 当child关闭文件描述符0后,0 是最小的文件描述符。因此open操作将使文件描述符0(标准输入)指向文件input.txt.xv6 shell中的I / O重定向代码完全以这种方式工作(user / sh.c:82)。
    • 现在应该清楚为什么将fork和exec分开调用是一个好主意? 因为如果它们是分开的,则shell可以fork一个child,在该child中使用open,close,dup来更改标准输入和输出文件描述符,然后exec。 不需要更改正在执行的程序(在我们的示例中为cat)。 如果将fork和exec组合到单个系统调用中,则shell将需要一些其他(可能更复杂)的方案来重定向标准输入和输出,或者程序本身将必须了解如何重定向I / O。
    • 尽管fork复制了文件描述符表,但每个潜在文件的偏移量在父级和子级之间共享。 考虑以下示例:
    if(fork() == 0) {
        write(1, "hello ", 6);
        exit(0);
    } else {
        wait(0);
        write(1, "worlden", 6);
    }
    
    • 在上例中,父进程和子进程都将写入文件描述符1.最后输出的数据是"hello world"
    • 父进程的写入会等到子进程写入后进行(由于wait)。两个文件描述符共享一个偏移量。
    • 此行为有助于从Shell命令序列产生顺序输出,例如(echo hello; echo world)> output.txt。
    • dup系统调用复制了一个现有的文件描述符,并返回了一个新的文件描述符,该描述符引用了相同的潜在I/O对象。两个文件描述符共享一个偏移量,就像fork所复制的文件描述符一样。这是将hello world写入文件的另一种方法:
    fd = dup(1);
    write(1, "hello ", 6);
    write(fd, "worlden", 6);
    
    • 如果两个文件描述符是通过fork和dup调用序列从同一原始文件描述符派生的,则它们共享一个偏移量。 否则,文件描述符不共享偏移量,即使它们是对同一文件的open产生的。 Dup允许shell执行以下命令: ls existing-file non-existing-file > tmp1 2>&1。 2>&1告诉shell将文件描述符2与描述符1相同。已存在文件的名称和文件不存在等错误消息都将显示在文件tmp1中。 xv6 Shell不支持错误文件描述符的I / O重定向,但是现在您知道如何实现它。
    • 文件描述符是一种强大的抽象,因为它们隐藏了它们所连接的对象的详细信息:写入文件描述符1的进程可能正在写入文件,诸如控制台的设备或管道。

    管道

    • 管道是一个小的内核缓冲区,以一对文件描述符的形式暴露给进程,一个用于读取,一个用于写入。
    • 将数据写入管道的一端可使该数据可从管道的另一端读取。 管道为流程进行通信提供了一种方法。 以下示例代码运行程序wc,使用标准输入连接到管道的读取端。
    int p[2];
    char *argv[2];
    argv[0] = "wc";
    argv[1] = 0;
    pipe(p);
    if(fork() == 0) {
        close(0);
        dup(p[0]);
        close(p[0]);
        close(p[1]);
        exec("/bin/wc", argv);
    } else {
        close(p[0]);
        write(p[1], "hello worlden", 12);
        close(p[1]);
    }
    
    * 程序调用pipe创建一个新管道,并将读取和写入文件描述符记录在数组p中。 在fork之后,父进程和子进程都具有引用管道的文件描述符。 子进程将读取端复制到文件描述符0上,关闭p中的文件描述符,然后执行wc。 当wc从其标准输入中读取时,它将从管道中读取。 父进程关闭管道的读取侧,写入管道,然后关闭写入侧。
    
    • 如果没有可用数据,则在管道上进行读取以等待写入数据或所有引用写入端的文件描述符被关闭; 在后一种情况下,读取将返回0,就像到达数据文件的末尾一样。 读取管道会一直堵塞直到无法接受到数据。因此,对于子进程来说,在执行上述wc之前关闭管道的写端很重要:如果wc进程的文件描述符之一引用了管道的写端,则wc将永远等不到文件末尾 。
    • xv6 shell实现了管道,例如grep fork sh.c | wc -l 类似于上面的代码(user / sh.c:100)。 子进程创建一个管道,以将管道的左端与右端连接起来。 然后,它在管道的左端调用fork和runcmd,在右端调用fork和runcmd,并等待两者都完成。 管道的右端可能是一个命令,该命令本身包括一个管道(例如a | b | c),该管道本身派生了两个新的子进程(一个用于b,一个用于c)。 因此,shell可以创建进程树。 该树的叶子是命令,内部节点是等待左右子节点完成的进程。 原则上,您可以让内部节点在管道的左端运行,但是这样做会使实现复杂化。
    • 管道似乎没有临时文件强大:echo hello world | wc
    • 可以在没有管道的情况下实现:
      echo hello world >/tmp/xyz; wc </tmp/xyz
    • 在这种情况下,管道比临时文件至少具有四个优点。 首先,管道会自动清理自己; 使用文件重定向,shell必须在完成后小心删除/ tmp / xyz。 其次,管道可以传递任意长的数据流,而文件重定向需要磁盘上有足够的可用空间来存储所有数据。 第三,管道允许并行执行管道阶段,而文件方法要求第一个程序在第二个程序启动之前完成。 第四,如果要实现进程间通信,则管道的读写锁比文件的 non-blocking语义更有效。

    文件系统

    • xv6文件系统提供了数据文件和目录,这些数据文件是原始的字节数组。目录包含对数据文件和其他目录的命名引用。 目录形成一棵树,从一个特殊的root目录开始。
    • 类似于/a/b/c的路径是指根目录/中名为a的文件夹中名为b的文件夹中名为c的文件或文件夹。
    • 不以/开头的路径是相对于调用进程的当前目录的。调用进程的当前目录可以通过chdir系统调用对其进行更改。
    • 下面这两个程序片段都打开同一个文件(假设文件存在)
    chdir("/a");
    chdir("b");
    open("c", O_RDONLY);
    
    open("/a/b/c", O_RDONLY);
    
    • 第一个代码片段将进程的当前目录更改为/a /b; 第二个既不引用也不更改进程的当前目录。
    • 有多个操作系统接口来创建新文件或文件夹:mkdir创建新文件夹,使用O_CREATE标志调用open将创建新数据文件,而mknod将创建新设备文件。 如下例所示:
    mkdir("/dir");
    fd = open("/dir/file", O_CREATE|O_WRONLY);
    close(fd);
    mknod("/console", 1, 1);
    

    Mknod在文件系统中创建一个文件,但是该文件没有内容。 但是,文件的元数据会将其标记为设备文件,并记录主设备号和次设备号(mknod的两个参数),它们唯一地标识内核设备。 当以后有一个进程打开文件时,内核会将read和write系统调用转换到内核设备的读写实现,而不是将它们转换到文件系统。

    fstat系统调用得到有关文件描述符引用的对象的信息。此对象信息返回结构体stat,定义在
    stat.h (kernel/stat.h):

    #define T_DIR 1 // Directory
    #define T_FILE 2 // File
    #define T_DEVICE 3 // Device
    struct stat {
        int dev; // File system’s disk device
        uint ino; // Inode number
        short type; // Type of file
        short nlink; // Number of links to file
        uint64 size; // Size of file in bytes
    };
    

    文件名与文件不同; 同一个文件(称为inode)可以具有多个名称(称为links)。
    link系统调用将创建另一个文件名称,该名称引用与现有文件相同的inode。 下面的程序片段创建了一个名为a又为b的新文件。

    open("a", O_CREATE|O_WRONLY);
    link("a", "b");
    

    读取,写入a与读取,写入到b相同。 每个inode由唯一的inode编号标识。 在上面的代码片段之后,可以通过检查fstat的结果确定a和b是否引用相同的文件:两者将返回相同的inode编号(ino),并且nlink将变为2。

    unlink系统调用从文件系统中删除一个名称。 仅当文件的link计数为零且没有文件描述符引用该文件时, 才会将inode和其所在的磁盘空间清除。

    因此当执行了

    unlink("a");
    

    之后,使用名称b任然能够访问文件。

    下面的程序片段是一种惯用的方式创建一个临时inode。

    fd = open("/tmp/xyz", O_CREATE|O_RDWR);
    unlink("/tmp/xyz");
    
    • 当fd文件描述符被关闭后,临时的inode将会被清除。
    • 用于文件系统操作的Shell命令是作为用户级程序(例如mkdir,ln,rm等)实现的。该设计允许任何人通过添加新的用户程序扩展Shell。在事后看来,似乎是理所当然的。
    • 但和Unix同时期的其他系统设计,通常将这样的命令构建到shell中(并将shell构建到内核中)。
    • cd是一个例外,它内置在shell中(user / sh.c:160)。 cd必须更改shell本身的当前工作目录。 如果cd以常规命令运行,那么shell将派生一个子进程,该子进程将运行cd,而cd会更改该子进程的工作目录。 父进程(即shell)的工作目录不会更改。

    总结

    Unix结合了文件描述符,管道和方便的shell语法以对其进行操作,这是编写通用可复用程序的重大进步。这是Unix的强大功能和广泛使用的原因,外壳程序是第一种所谓的“脚本语言”。Unixit系统调用接口在BSD,Linux,和Mac OSX 上广泛使用。

    • Unix系统调用接口已通过可移植操作系统接口(POSIX)标准进行了标准化。 Xv6不兼容POSIX。 它抛弃一些了系统调用(包括诸如lseek之类的基本调用),仅部分实现了系统调用以及其他差异。 xv6的主要目标是简单性和清晰度,同时提供简单的类UNIX系统调用接口。 为了运行基本的Unix程序,一些人用更多的系统调用和一个简单的C库扩展了xv6。 但是,与xv6相比,现代内核提供了更多的系统调用和内核服务。 例如,它们支持联网,窗口系统,用户级线程,许多设备的驱动程序等。 现代内核不断快速发展,并提供了POSIX以外的许多功能。
    • 在很大程度上,现代Unix派生的操作系统没有遵循早期的Unix模型,即将设备公开为特殊文件,例如上面讨论的控制台设备文件。Unix的作者继续构建Plan9,将“资源即文件”概念应用于现代设施,将网络,图形和其他资源表示为文件或文件树。
    • 文件系统和文件描述符是强大的抽象。 即使这样,也存在其他模型。 Multics是Unix的前身,它以一种类似于内存的方式抽象了文件存储,从而产生了截然不同的界面风格。 Multics设计的复杂性直接影响了Unix的设计师,后者试图构建更简单的东西。
    • 本书探讨了xv6如何实现其类似Unix的接口,但是这些思想和概念不仅适用于Unix。 任何操作系统都必须将进程多路复用到基础硬件上,将进程彼此隔离,并提供用于受控的进程间通信的机制。 研究xv6之后,您应该能够查看其他更复杂的操作系统,

    参考资料

    https://dreamerjonson.com/2020/01/04/6-s081-1/https://pdos.csail.mit.edu/6.828/2019/labs/util.htmlhttps://pdos.csail.mit.edu/6.828/2019/xv6/book-riscv-rev0.pdfhttps://pdos.csail.mit.edu/6.828/2019/lec/l-overview.txt

    更多原创文章干货分享,请关注公众号

    8361164a3f73805101e71e79cb0e7d27.png

    加技术交流群请加微信(注明:交流群):ywj2271840211

    展开全文
  • SpringBlade :SpringBlade 是一个由商业级项目升级优化而来 SpringCloud 分布式微服务架构、SpringBoot 单体式微服务架构并存综合型项目,采用 Java8 API 重构了业务代码,完全遵循阿里巴巴编码规范。...
  • 相同的服务部署多份,避免单点故障。 超时和重试机制 一旦用户的请求超过某个时间得不到响应就结束此次请求并抛出异常。 如果不进行超时设置可能会导致请求响应速度慢,甚至导致请求堆积进而让系统无法在处理请求。...
  • 相同的服务部署多份,避免单点故障。 超时和重试机制 一旦用户的请求超过某个时间得不到响应就结束此次请求并抛出异常。 如果不进行超时设置可能会导致请求响应速度慢,甚至导致请求堆积进而让系统无法在处理请求。...
  • java源码包2

    千次下载 热门讨论 2013-04-20 11:28:17
    2个目标文件,FTP目标是:(1)提高文件共享性(计算机程序和/或数据),(2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间文件存储系统导致变化,(4)为了可靠和高效地传输,虽然用户...
  •  GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收...
  • 尹成JAVA快速入门

    2020-12-08 15:12:43
    例如,Java类是根据需要载入,甚至有些是通过网络获取的。   尹成老师带你步入Java语言基础殿堂,讲课生动风趣、深入浅出,全套视频内容充实,整个教程以Java语言为核心,完整精彩演练了Java语言操作...
  • java开源包1

    千次下载 热门讨论 2013-06-28 09:14:34
    Spring4GWT ...JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and PNML (XML based)文件格式。使用了优秀的JHotDraw 5.2 框架。 activemq...
  • java开源包12

    热门讨论 2013-06-28 10:14:45
    Spring4GWT ...JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and PNML (XML based)文件格式。使用了优秀的JHotDraw 5.2 框架。 activemq...
  • Java资源包01

    2016-08-31 09:16:25
    Spring4GWT ...JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and PNML (XML based)文件格式。使用了优秀的JHotDraw 5.2 框架。 activemq...
  • java开源包101

    2016-07-13 10:11:08
    Spring4GWT ...JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and PNML (XML based)文件格式。使用了优秀的JHotDraw 5.2 框架。 activemq...
  • java开源包11

    热门讨论 2013-06-28 10:10:38
    Spring4GWT ...JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and PNML (XML based)文件格式。使用了优秀的JHotDraw 5.2 框架。 activemq...
  • java开源包2

    热门讨论 2013-06-28 09:17:39
    Spring4GWT ...JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and PNML (XML based)文件格式。使用了优秀的JHotDraw 5.2 框架。 activemq...
  • java源码包3

    千次下载 热门讨论 2013-04-20 11:30:13
    2个目标文件,FTP目标是:(1)提高文件共享性(计算机程序和/或数据),(2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间文件存储系统导致变化,(4)为了可靠和高效地传输,虽然用户...
  • java开源包3

    热门讨论 2013-06-28 09:20:52
    Spring4GWT ...JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and PNML (XML based)文件格式。使用了优秀的JHotDraw 5.2 框架。 activemq...
  • java开源包6

    热门讨论 2013-06-28 09:48:32
    Spring4GWT ...JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and PNML (XML based)文件格式。使用了优秀的JHotDraw 5.2 框架。 activemq...
  • java开源包5

    热门讨论 2013-06-28 09:38:46
    Spring4GWT ...JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and PNML (XML based)文件格式。使用了优秀的JHotDraw 5.2 框架。 activemq...
  • java源码包4

    千次下载 热门讨论 2013-04-20 11:31:44
    2个目标文件,FTP目标是:(1)提高文件共享性(计算机程序和/或数据),(2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间文件存储系统导致变化,(4)为了可靠和高效地传输,虽然用户...
  • java开源包10

    热门讨论 2013-06-28 10:06:40
    Spring4GWT ...JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and PNML (XML based)文件格式。使用了优秀的JHotDraw 5.2 框架。 activemq...
  • java开源包4

    热门讨论 2013-06-28 09:26:54
    Spring4GWT ...JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and PNML (XML based)文件格式。使用了优秀的JHotDraw 5.2 框架。 activemq...
  • java开源包8

    热门讨论 2013-06-28 09:55:26
    Spring4GWT ...JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and PNML (XML based)文件格式。使用了优秀的JHotDraw 5.2 框架。 activemq...
  • java开源包9

    热门讨论 2013-06-28 09:58:55
    Spring4GWT ...JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and PNML (XML based)文件格式。使用了优秀的JHotDraw 5.2 框架。 activemq...
  • java开源包7

    热门讨论 2013-06-28 09:52:16
    Spring4GWT ...JARP是为petri 网提供的一个Java编辑器,基于ARP分析器。可以将网络图导出为 GIF, JPEG, PNG, PPM, ARP and PNML (XML based)文件格式。使用了优秀的JHotDraw 5.2 框架。 activemq...
  • 微型计算机的普及加速了计算机网络广泛应用和飞速发展。BBS全称为Bulletin Board System(电子公告板)或者Bulletin Board Service(公告板服务)。是Internet上一种电子信息服务系统。它提供一块公共电子白板,...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 188
精华内容 75
关键字:

java获取计算机提供的服务

java 订阅