mount 使用方法详解

mount是linux很常用的命令,用于挂载各种设备(包括本地block设备,NFS,虚拟设备等),umount用于卸载设备。如果挂载一个设备到一个目录中,则通过该目录可以访问设备的文件(必须有权限访问),而原来目录的内容会暂时性隐藏(不会覆盖,卸载后恢复可见)。

mount最常用的使用方式为:

mount device dir

比如 mount /dev/sda1 /mnt

这是mount会自动检测设备的文件系统(如果可能的话,比如fstab,mtab中配置有),如果检测失败,需要指定文件系统类型,使用-t选项指定,比如

mount -t btrfs /dev/sda1  /mnt

/etc/fstab是系统默认挂载的配置,在系统启动时会自动挂载该文件下的设备(设置选项noauto除外。

如果你修改了该文件,你也可以使用 mount -a使系统重新读取该文件进行挂载。

在/etc/mtab会记录当前的挂载状况(在/proc/mounts也记录),当使用mount命令不加任何参数时,默认打印该文件的内容。

你也可以使用-l选项打印当前的挂载状况,使用-t选项过滤打印的文件系统类型。

以前一个设备只能挂载在一个地方,从内核2.4以后,支持把一个目录挂载到另一个目录,这时相当于相同文件内容可以同时有多个访问点(这在chroot中很有用,想想我在新的root中怎么访问/proc /dev目录),使用--bind 或者-B选项挂载目录

比如

mount --bind -t tmpfs /dev/  newDev

mount --bind -t proc /proc newProc

注意使用bind选项只能挂载指定目录下的内容,如果该目录下又有子挂载点,不会自动挂载,使用rbind选项,可以递归挂载,甚至可以挂载/ 到另一个目录中。

比如

mount --rbind -t ext4 / newRoot

不过挂载了就不能卸载了,因为该目录正使用(busy),可以使用lsof命令查看(可以使用--move选项,见以下)。

有时我们不想有人bind,可以使用mount --make-unbindable或者--make-runbindable(递归式)选项设置。比如

mount --make-runbindable /

不能再bind根目录了。

--move选项可以把一个挂载点移动到另一个目录,如

mount --move -t ext4 /mnt /media

-r(或者-o ro)选项指定只读挂载,访问挂载点只能读取内容,不能写,-w(或者-o rw)指定挂载为读写方式,这也是默认方式。

-o 指定挂载选项(多个选项使用逗号分隔),以上已经介绍了ro和rw选项,下面简单介绍下挂载选项:

auto ,再/etc/fstab下指定,使用mount -a时或者系统启动时自动挂载,使用noauto相反。

defaults使用默认挂载选项,相当于rw,suid,dev,exec,auto,nouser,async

dev 说明这是字符设备或者块设备,而不是虚拟设备,相反nodev说明可能是虚拟设备

exec,在挂载点可以执行文件,noexec说明在挂载点上不能执行文件,有一次我在家目录下不小心指定了noexec,写了个c程序,运行./a.out出错,后面发现原来是指定了noexec选项

group 一般文件系统挂载只能root身份才有权限,在fstab下指定group,则属于设备组的用户可以挂载。

owner指定设备的所有者可以挂载,比如某设备属于Mary,则root和Mary都有权限挂载。

remount,重新挂载已经挂载的设备,用于覆盖原来的选项,比如原来的文件系统/dev/sda1是只读的,挂载在/mnt下,则可以使用

mount -o remount,rw /dev/sda1 /mnt 重新挂载,并且可读写。

user 用于fstab文件,任何普通用户都可以挂载该设备。

nouser用于fstab,表明只有root可以挂载,这是默认行为。

还有一些选项,专门针对指定的文件系统,比如ext2的errors。

mount还可以用于挂载loop设备,比如iso镜像,img文件等。此时需要指定文件系统类型(-t)和loop选项,比如

mount -t ext4 -o loop ubuntu.iso /mnt

mount -t iso9660 -o loop ubuntu.iso /mnt

卸载loop设备使用命令losetup -d 或者umount -d

试一下

dd if=/dev/zero of=tmp.img bs=500m count=2

mkfs.ext4 tmp.img

mount -t ext4 tmp.img /mnt

使用mount可以挂载iso文件,但磁盘格式为qcow2则不能直接挂载了,可以查看以前的文章挂载http://krystism.is-programmer.com/posts/47074.html。

 

 

 

 

 

转载请注明:http://krystism.is-programmer.com/若有错误,请多多指正,谢谢!

java无回显的密码输入

在java6中有一个新类Console,能够实现无回显输入,用于安全输入!以下是代码样例:

import java.io.*;
import java.util.*;
public class ConsoleDemo {
    public static void main(String[] args) {
        Console console = System.console();
        if (console == null) {
            System.err.println("Failed to get console!");
            return;
        }
        String name = console.readLine("Please type your name:");
        char[] password1 = null;
        char[] password2 = null;
        console.printf("Your name is %s\n", name);
        password1 = console.readPassword("Please type your password:");
        password2 = console.readPassword("Please type your password again:");
        if (!Arrays.equals(password1, password2)) {
            System.err.println("Password doesn't match the confirmation.");
            return;
        }
        console.printf("Hi, %s, Your password is '%s'\n", name,  new String(password1));
        Arrays.fill(password1, '\0'); /* 安全清理 */
        Arrays.fill(password2, '\0');
    }
}
转载请注明:http://krystism.is-programmer.com/若有错误,请多多指正,谢谢!

调用Arrays.asList(arr).contains(value)判断数组是否存在某个元素?

这个问题很简单,就是在一个无序数组中判断某个元素是否存在,当然如果自己定义数据结构,可以使用trie,hash,如果不要求完全准确,允许误判,还能使用布隆!显然不能使用二分搜索,因为数组是无序的!当我们要经常搜索时,排序是必要的,或者使用其他数据结构。

这篇文章讨论了下http://www.programcreek.com/2014/04/check-if-array-contains-a-value-java/#more-12168,于是自己测试了下,下面是我的代码(必须使用java8版本以上):

import java.util.*;
interface StringPolicy {
	boolean contains(String[] arr, String value);
}
interface LongPolicy {
	boolean contains(long[] arr, long value);
}
class Policies {
	
    public static boolean useList(String[] arr, String value) {
        return Arrays.asList(arr).contains(value);
    }
    public static boolean useList(long[] arr, long value) {
    	return Arrays.asList(arr).contains(value);
    }
    public static boolean useSet(String[] arr, String value) {
        return new HashSet<>(Arrays.asList(arr)).contains(value);
    }
    public static boolean useSet(long[] arr, long value) {
        return new HashSet<>(Arrays.asList(arr)).contains(value);
    }
    public static boolean useLoop(String[] arr, String value) {
        for (String s : arr) {
            if (s.equals(value))
                return true;
        }
        return false;
    }
    public static boolean useLoop(long[] arr, long value) {
    	for (long l : arr) {
    		if (l == value)
    			return true;
    	}
    	return false;
    }
    public static boolean useStream(String[] arr, String value) {
    	return Arrays.stream(arr).anyMatch(value::equals);
    }
    public static boolean useStream(long[] arr, long value) {
    	return Arrays.stream(arr).anyMatch(l -> l == value);
    }
    public static boolean useParallelStream(String[] arr, String value) {
    	return Arrays.stream(arr).parallel().anyMatch(value::equals);
    }
    public static boolean useParallelStream(long[] arr, long value) {
    	return Arrays.stream(arr).parallel().anyMatch(l -> l == value);
    }
}
public class SearchDemo {
	public static void fill(String[] arr) {
        for(int i = 0; i < arr.length; ++i) {
            arr[i] = String.valueOf(i + 1);
        }
    }
	public static void fill(long[] arr) {
		for (int i = 0; i < arr.length; ++i) {
			arr[i] = i + 1;
		}
	}
	public static void fill(String[] arr, String value) {
		Arrays.fill(arr, value);
	}
	public static void fill(long[] arr, long value) {
		Arrays.fill(arr, value);
	}
	public static void test(String name, StringPolicy p, String[] arr, String value, int times) {
		long start = System.nanoTime();
		for (int i = 0; i < times; ++i) {
			p.contains(arr, value);
		}
		long end = System.nanoTime();
		long d = (end - start) / 1_000_000;
		System.out.printf("%s: %d\n", name, d);
	}
	public static void test(String name, LongPolicy p, long[] arr, long value, int times) {
		long start = System.nanoTime();
		for (int i = 0; i < times; ++i) {
			p.contains(arr, value);
		}
		long end = System.nanoTime();
		long d = (end - start) / 1_000_000;
		System.out.printf("%s: %d\n", name, d);
	}
	public static void main(String[] args) {
		String[] arr1 = new String[10_000];
		long[] arr2 = new long[10_000];
		fill(arr1);
		fill(arr2);
		System.out.println("******************* String **************************");
		test("useLoop", Policies::useLoop, arr1, "A", 10_000);
		test("useList", Policies::useList, arr1, "A", 10_000);
		test("useSet", Policies::useSet, arr1, "A", 10_000);
		test("useStream", Policies::useStream, arr1, "A", 10_000);
		test("useParallelStream", Policies::useParallelStream, arr1, "A", 10_000);
		System.out.println("******************* Long **************************");
		test("useLoop", Policies::useLoop, arr2, -1, 10_000);
		test("useList", Policies::useList, arr2, -1, 10_000);
		test("useSet", Policies::useSet, arr2, -1, 10_000);
		test("useStream", Policies::useStream, arr2, -1, 10_000);
		test("useParallelStream", Policies::useParallelStream, arr2, -1, 10_000);
	}

结果输出是:

数组大小为1k时的结果:
******************* String **************************
useLoop: 141
useList: 128
useSet: 859
useStream: 331
useParallelStream: 746
******************* Long **************************
useLoop: 87
useList: 7
useSet: 40
useStream: 311
useParallelStream: 835
数组大小为10k时的结果:
******************* String **************************
useLoop: 887
useList: 1005
useSet: 7889
useStream: 2489
useParallelStream: 2420
******************* Long **************************
useLoop: 644
useList: 10
useSet: 24
useStream: 2455
useParallelStream: 2748
当把数组大小提高到100k时,结果为:
******************* String **************************
useLoop: 10584
useList: 11597
useSet: 92295
useStream: 31249
useParallelStream: 17176
******************* Long **************************
useLoop: 6167
useList: 10
useSet: 33
useStream: 22633
useParallelStream: 21192
 
可以看出使用字符串时,使用循环的方式会比其他方式更快,但当判断基本数据类型时,使用List是最快的,往往使用Set都不是好方法,使用Stream也并没有提高速率。原文并没有说明!
 
转载请注明:http://krystism.is-programmer.com/若有错误,请多多指正,谢谢!

java中使用private构造方法不能实现单例模式

众所周知,一般使用java实现单例模式有两种方法,分别为急切式(饥饿式)和双重加锁式,急切式就是在声明时即创建,这样在类加载时就已经创建好了,即时我们可能并不不需要它,它的生命周期是永久的,造成内存泄漏的可能!第二种方式是lazy的,只有在使用时创建,实现了延迟加载。代码为

1.急切式

class Singleton {
    private final static Singleton instance = new Singleton();
    private Singleton(){
    }
    public static Singleton getInstance() {
        return instance;
    }
}

2. 双重加锁式

class Singleton {
    private volatile static Singleton instance = null;
    private Singleton(){

    }
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized(Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

还有一种方法是使用内部类的方法,这主要为克服方法1中的问题,既能实现延迟加载,又能保证线程安全,而且性能不错。代码为:

class Singleton {
    private Singleton() {

    }
    private static class Holder {
        private static final Singleton INSTANCE = new Singleton();
    }
    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }
}

以上方法都是通过使用private构造方法来阻止外部直接创建对象,但如果使用反射机制,则不能保证实例的唯一性了!!!

public class SingletonDemo {
    //@SuppressWarnings("unchecked")
    //public static <T> T newInstance(Class<?> cl) {
    //    T t = null;
    //    try {
    //        t = (T)cl.newInstance(); /* 只能调用public构造方法 */
    //    } catch(Exception e) {
    //        e.printStackTrace();
    //    }
    //    return t;
    //}
    @SuppressWarnings("unchecked")
    public static <T> T newInstance(Class<?> cl) {
        T t = null;
        try {
            Constructor<?> constructor = cl.getDeclaredConstructor();
            constructor.setAccessible(true);
            t = (T)constructor.newInstance();
        } catch(Exception e) {
            e.printStackTrace();
        }
        return t;
    }
    @SuppressWarnings("unchecked")
    public static <T> T newInstance(Class<?> cl, Class<?>...args) {
        T t = null;
        try {
            Constructor<?> constructor = cl.getDeclaredConstructor(args);
            constructor.setAccessible(true);
            t = (T)constructor.newInstance("name", 1);
        } catch(Exception e) {
            e.printStackTrace();
        }
        return t;
    }
    public static void main(String[] args) {
        Singleton instance = Single.INSTANCE;
        Singleton s1 = newInstance(Singleton.class, String.class, int.class);
        Singleton s2 = newInstance(Singleton.class, String.class, int.class);
        //Tmp t1 = newInstance(Tmp.class);
        //Tmp t2 = newInstance(Tmp.class);
        //System.out.println(s1 == s2);
        //System.out.println(t1 == t2);
    }
}

Joshua Bloch (Effect java 作者)提出一种新的方法实现单例模式,就是使用Enum(其实也是类,一种特殊的类,构造方法必须是private ,final的)!如下:

 

enum Singleton {
    INSTANCE;
    public void sayHi() {
        System.out.println("Hi");
    }
}

这样当试图通过反射机制创建对象时,会抛出异常!

转载请注明:http://krystism.is-programmer.com/若有错误,请多多指正,谢谢!

java同步工具Phaser

从java7开始在concurrent包中加入了Phaser类,它几乎可以取代CountDownLatch和CyclicBarrier, 其功能更灵活,更强大,支持动态调整需要控制的线程数。下面以一个具体实例说明这个Phaser类的用处,相信理解这个例子后,其功能不言而喻。

例子:有若干考生参加考试,考试科目是统一的,考试顺序为语文、数学、英语共三门,若其中一门挂科,则不能参加后面的考试。现在假设考试时间不受限制,开考时间以最后一名考完上一科时间为准,即先考完的考生并且成绩合格,需要参加下一门考试,则必须等待所有考生考完当科。

import java.util.*;
import java.util.concurrent.*;
class Examinee implements Runnable {
    public static Random random = new Random(new Date().getTime());
    private String name;
    private Phaser phaser;
    private int english;
    private int chinese;
    private int math;
    public Examinee(String name, Phaser phaser) {
        this.name = name;
        this.phaser = phaser;
    }
    public boolean english() {
        int time = random.nextInt(10);
        try {
            TimeUnit.SECONDS.sleep(time); /* 考试时间是一个随机数 */
        } catch (Exception e) {
            e.printStackTrace(System.err);
        }
        english = random.nextInt(101) ; /* 假定考试成绩是随机的 */
        if (english < 60) {
            System.out.printf("%s Failed to pass English!\n", name);
            phaser.arriveAndDeregister(); /* 考试不合格,取消考试资格 */
            return false;
        } else {
            phaser.arriveAndAwaitAdvance(); /* 通过考试,可以进行下一门考试 */
            return true;
        }
    }
    public boolean chinese() {
        int time = random.nextInt(10);
        try {
            TimeUnit.SECONDS.sleep(time);
        } catch (Exception e) {
            e.printStackTrace(System.err);
        }
        chinese = random.nextInt(101) ;
        if (chinese < 60) {
            System.out.printf("%s Failed to pass Chinese!\n", name);
            phaser.arriveAndDeregister();
            return false;
        } else {
            phaser.arriveAndAwaitAdvance();
            return true;
        }
    }
    public boolean math() {
        int time = random.nextInt(10);
        try {
            TimeUnit.SECONDS.sleep(time);
        } catch (Exception e) {
            e.printStackTrace(System.err);
        }
        math = random.nextInt(101) ;
        if (math < 60) {
            System.out.printf("%s Failed to pass Math!\n", name);
            phaser.arriveAndDeregister();
            return false;
        } else {
            phaser.arriveAndAwaitAdvance();
            return true;
        }
    }
    public void showInfo() {
        System.out.printf("%s\tChinese:%d\tEnglish:%d\tMath:%d\n", name, chinese, english, math);
        phaser.arriveAndDeregister();
    }
    @Override
    public void run() {
        phaser.arriveAndAwaitAdvance(); /* 等待考生做好准备,即在同一个起跑线上 */
        System.out.printf("%s is ready!\n", name);
        if (!chinese() || !english() || !math())
            return;
        showInfo(); /* 只显示所有科目均合格的考生分数 */
    }
}
public class PhaserDemo2 {
    public static void main(String[] args) {
        final String[] names = {"Jim", "Hary", "Mary", "Jhon", "Ali", "Lucy", "Wang", "Zhang", "Li", "Uhm", "Hey", "Gu", "Asu", "Who"};
        Phaser phaser = new Phaser(names.length);
        List<Thread> threads = new ArrayList<>(names.length);
        for (String name : names) {
            threads.add(new Thread(new Examinee(name, phaser), name)); /* 创建各个考生线程 */
        } 
        for (Thread t : threads) {
            t.start(); /* 开始考试 */
        }
        for (Thread t : threads) {
            try {
                t.join(); /* 等待考试结束 */
            } catch (InterruptedException e) {
                e.printStackTrace(System.err);
            }
        }
        System.out.printf("Terminal ? %s\n", phaser.isTerminated());
    }
}

由上面的例子,可以看出Phaser的功能。其中arrive方法很像CountDownLatch的countDown方法和CyclicBarrier的await方法,请自行比较之!Phaser类还有很多其他的功能,可以查看其API文档。

转载请注明:http://krystism.is-programmer.com/若有错误,请多多指正,谢谢!