天道酬勤,学无止境

Delete a mutex from another process

Using the topic Overview - Handle Enumeration, number 5, the attempt Close mutex of another process and and information from Mutex analysis, the canary in the coal mine and discovering new families of malware/, I have came up with:

Attempt 1: http://pastebin.com/QU0WBgE5

You must open Notepad first. Needless to say, this is not working for me. I need better error checking to figure out what's going on. I don't know how to get mutex pointers in the format I see them in Process Explorer.

My goal is to be able to delete/kill of the mutex handles created by a process so more than one instance can be open. I can do this manually using Process Explorer, but I want to do it programmatically.


(Based on Yahia's notes, I need more permissions.)

Attempt 2: http://pastebin.com/yyQLhesP

At least now I have some sort of error checking, most of the time DuplicateHandle returns 6 or 5, which is an invalid handle and access denied respectfully.


Working attempt (kind of):

I actually didn't require anything Yahia stated in the end. I was getting a "local" handle when I needed a remote one. Basically, what I mean is that you have to find the HandleValue using NtQuerySystemInformation and use that handle, not the one returned by OpenMutex / CreateMutex.

Granted, I can't get it to work on some applications (osk.exe -- on screen keyboard), but it worked for the application I was going for, posting code in case someone wants to take it further.

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Text;
using System.Threading;
using System.Security.AccessControl;
using System.Security.Principal;
namespace FileLockInfo
{

    public class Win32API
    {
        [DllImport("ntdll.dll")]
        public static extern int NtQueryObject(IntPtr ObjectHandle, int
            ObjectInformationClass, IntPtr ObjectInformation, int ObjectInformationLength,
            ref int returnLength);

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern uint QueryDosDevice(string lpDeviceName, StringBuilder lpTargetPath, int ucchMax);

        [DllImport("ntdll.dll")]
        public static extern uint NtQuerySystemInformation(int
            SystemInformationClass, IntPtr SystemInformation, int SystemInformationLength,
            ref int returnLength);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr OpenMutex(UInt32 desiredAccess, bool inheritHandle, string name);

        [DllImport("kernel32.dll")]
        public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);

        [DllImport("kernel32.dll")]
        public static extern int CloseHandle(IntPtr hObject);

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool DuplicateHandle(IntPtr hSourceProcessHandle,
           ushort hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr lpTargetHandle,
           uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwOptions);

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetCurrentProcess();

        public enum ObjectInformationClass : int
        {
            ObjectBasicInformation = 0,
            ObjectNameInformation = 1,
            ObjectTypeInformation = 2,
            ObjectAllTypesInformation = 3,
            ObjectHandleInformation = 4
        }

        [Flags]
        public enum ProcessAccessFlags : uint
        {
            All = 0x001F0FFF,
            Terminate = 0x00000001,
            CreateThread = 0x00000002,
            VMOperation = 0x00000008,
            VMRead = 0x00000010,
            VMWrite = 0x00000020,
            DupHandle = 0x00000040,
            SetInformation = 0x00000200,
            QueryInformation = 0x00000400,
            Synchronize = 0x00100000
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct OBJECT_BASIC_INFORMATION
        { // Information Class 0
            public int Attributes;
            public int GrantedAccess;
            public int HandleCount;
            public int PointerCount;
            public int PagedPoolUsage;
            public int NonPagedPoolUsage;
            public int Reserved1;
            public int Reserved2;
            public int Reserved3;
            public int NameInformationLength;
            public int TypeInformationLength;
            public int SecurityDescriptorLength;
            public System.Runtime.InteropServices.ComTypes.FILETIME CreateTime;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct OBJECT_TYPE_INFORMATION
        { // Information Class 2
            public UNICODE_STRING Name;
            public int ObjectCount;
            public int HandleCount;
            public int Reserved1;
            public int Reserved2;
            public int Reserved3;
            public int Reserved4;
            public int PeakObjectCount;
            public int PeakHandleCount;
            public int Reserved5;
            public int Reserved6;
            public int Reserved7;
            public int Reserved8;
            public int InvalidAttributes;
            public GENERIC_MAPPING GenericMapping;
            public int ValidAccess;
            public byte Unknown;
            public byte MaintainHandleDatabase;
            public int PoolType;
            public int PagedPoolUsage;
            public int NonPagedPoolUsage;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct OBJECT_NAME_INFORMATION
        { // Information Class 1
            public UNICODE_STRING Name;
        }

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct UNICODE_STRING
        {
            public ushort Length;
            public ushort MaximumLength;
            public IntPtr Buffer;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct GENERIC_MAPPING
        {
            public int GenericRead;
            public int GenericWrite;
            public int GenericExecute;
            public int GenericAll;
        }

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct SYSTEM_HANDLE_INFORMATION
        { // Information Class 16
            public int ProcessID;
            public byte ObjectTypeNumber;
            public byte Flags; // 0x01 = PROTECT_FROM_CLOSE, 0x02 = INHERIT
            public ushort Handle;
            public int Object_Pointer;
            public UInt32 GrantedAccess;
        }

        public const int MAX_PATH = 260;
        public const uint STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
        public const int DUPLICATE_SAME_ACCESS = 0x2;
        public const int DUPLICATE_CLOSE_SOURCE = 0x1;
    }

    public class Win32Processes
    {
        const int CNST_SYSTEM_HANDLE_INFORMATION = 16;
        const uint STATUS_INFO_LENGTH_MISMATCH = 0xc0000004;

        public static string getObjectTypeName(Win32API.SYSTEM_HANDLE_INFORMATION shHandle, Process process)
        {
            IntPtr m_ipProcessHwnd = Win32API.OpenProcess(Win32API.ProcessAccessFlags.All, false, process.Id);
            IntPtr ipHandle = IntPtr.Zero;
            var objBasic = new Win32API.OBJECT_BASIC_INFORMATION();
            IntPtr ipBasic = IntPtr.Zero;
            var objObjectType = new Win32API.OBJECT_TYPE_INFORMATION();
            IntPtr ipObjectType = IntPtr.Zero;
            IntPtr ipObjectName = IntPtr.Zero;
            string strObjectTypeName = "";
            int nLength = 0;
            int nReturn = 0;
            IntPtr ipTemp = IntPtr.Zero;

            if (!Win32API.DuplicateHandle(m_ipProcessHwnd, shHandle.Handle,
                                          Win32API.GetCurrentProcess(), out ipHandle,
                                          0, false, Win32API.DUPLICATE_SAME_ACCESS))
                return null;

            ipBasic = Marshal.AllocHGlobal(Marshal.SizeOf(objBasic));
            Win32API.NtQueryObject(ipHandle, (int)Win32API.ObjectInformationClass.ObjectBasicInformation,
                                   ipBasic, Marshal.SizeOf(objBasic), ref nLength);
            objBasic = (Win32API.OBJECT_BASIC_INFORMATION)Marshal.PtrToStructure(ipBasic, objBasic.GetType());
            Marshal.FreeHGlobal(ipBasic);

            ipObjectType = Marshal.AllocHGlobal(objBasic.TypeInformationLength);
            nLength = objBasic.TypeInformationLength;
            while ((uint)(nReturn = Win32API.NtQueryObject(
                ipHandle, (int)Win32API.ObjectInformationClass.ObjectTypeInformation, ipObjectType,
                  nLength, ref nLength)) ==
                Win32API.STATUS_INFO_LENGTH_MISMATCH)
            {
                Marshal.FreeHGlobal(ipObjectType);
                ipObjectType = Marshal.AllocHGlobal(nLength);
            }

            objObjectType = (Win32API.OBJECT_TYPE_INFORMATION)Marshal.PtrToStructure(ipObjectType, objObjectType.GetType());
            if (Is64Bits())
            {
                ipTemp = new IntPtr(Convert.ToInt64(objObjectType.Name.Buffer.ToString(), 10) >> 32);
            }
            else
            {
                ipTemp = objObjectType.Name.Buffer;
            }

            strObjectTypeName = Marshal.PtrToStringUni(ipTemp, objObjectType.Name.Length >> 1);
            Marshal.FreeHGlobal(ipObjectType);
            return strObjectTypeName;
        }


        public static string getObjectName(Win32API.SYSTEM_HANDLE_INFORMATION shHandle, Process process)
        {
            IntPtr m_ipProcessHwnd = Win32API.OpenProcess(Win32API.ProcessAccessFlags.All, false, process.Id);
            IntPtr ipHandle = IntPtr.Zero;
            var objBasic = new Win32API.OBJECT_BASIC_INFORMATION();
            IntPtr ipBasic = IntPtr.Zero;
            IntPtr ipObjectType = IntPtr.Zero;
            var objObjectName = new Win32API.OBJECT_NAME_INFORMATION();
            IntPtr ipObjectName = IntPtr.Zero;
            string strObjectName = "";
            int nLength = 0;
            int nReturn = 0;
            IntPtr ipTemp = IntPtr.Zero;

            if (!Win32API.DuplicateHandle(m_ipProcessHwnd, shHandle.Handle, Win32API.GetCurrentProcess(),
                                          out ipHandle, 0, false, Win32API.DUPLICATE_SAME_ACCESS))
                return null;

            ipBasic = Marshal.AllocHGlobal(Marshal.SizeOf(objBasic));
            Win32API.NtQueryObject(ipHandle, (int)Win32API.ObjectInformationClass.ObjectBasicInformation,
                                   ipBasic, Marshal.SizeOf(objBasic), ref nLength);
            objBasic = (Win32API.OBJECT_BASIC_INFORMATION)Marshal.PtrToStructure(ipBasic, objBasic.GetType());
            Marshal.FreeHGlobal(ipBasic);


            nLength = objBasic.NameInformationLength;

            ipObjectName = Marshal.AllocHGlobal(nLength);
            while ((uint)(nReturn = Win32API.NtQueryObject(
                     ipHandle, (int)Win32API.ObjectInformationClass.ObjectNameInformation,
                     ipObjectName, nLength, ref nLength))
                   == Win32API.STATUS_INFO_LENGTH_MISMATCH)
            {
                Marshal.FreeHGlobal(ipObjectName);
                ipObjectName = Marshal.AllocHGlobal(nLength);
            }
            objObjectName = (Win32API.OBJECT_NAME_INFORMATION)Marshal.PtrToStructure(ipObjectName, objObjectName.GetType());

            if (Is64Bits())
            {
                ipTemp = new IntPtr(Convert.ToInt64(objObjectName.Name.Buffer.ToString(), 10) >> 32);
            }
            else
            {
                ipTemp = objObjectName.Name.Buffer;
            }

            if (ipTemp != IntPtr.Zero)
            {

                byte[] baTemp2 = new byte[nLength];
                try
                {
                    Marshal.Copy(ipTemp, baTemp2, 0, nLength);

                    strObjectName = Marshal.PtrToStringUni(Is64Bits() ?
                                                           new IntPtr(ipTemp.ToInt64()) :
                                                           new IntPtr(ipTemp.ToInt32()));
                    return strObjectName;
                }
                catch (AccessViolationException)
                {
                    return null;
                }
                finally
                {
                    Marshal.FreeHGlobal(ipObjectName);
                    Win32API.CloseHandle(ipHandle);
                }
            }
            return null;
        }

        public static List<Win32API.SYSTEM_HANDLE_INFORMATION>
        GetHandles(Process process = null, string IN_strObjectTypeName = null, string IN_strObjectName = null)
        {
            uint nStatus;
            int nHandleInfoSize = 0x10000;
            IntPtr ipHandlePointer = Marshal.AllocHGlobal(nHandleInfoSize);
            int nLength = 0;
            IntPtr ipHandle = IntPtr.Zero;

            while ((nStatus = Win32API.NtQuerySystemInformation(CNST_SYSTEM_HANDLE_INFORMATION, ipHandlePointer,
                                                                nHandleInfoSize, ref nLength)) ==
                    STATUS_INFO_LENGTH_MISMATCH)
            {
                nHandleInfoSize = nLength;
                Marshal.FreeHGlobal(ipHandlePointer);
                ipHandlePointer = Marshal.AllocHGlobal(nLength);
            }

            byte[] baTemp = new byte[nLength];
            Marshal.Copy(ipHandlePointer, baTemp, 0, nLength);

            long lHandleCount = 0;
            if (Is64Bits())
            {
                lHandleCount = Marshal.ReadInt64(ipHandlePointer);
                ipHandle = new IntPtr(ipHandlePointer.ToInt64() + 8);
            }
            else
            {
                lHandleCount = Marshal.ReadInt32(ipHandlePointer);
                ipHandle = new IntPtr(ipHandlePointer.ToInt32() + 4);
            }

            Win32API.SYSTEM_HANDLE_INFORMATION shHandle;
            List<Win32API.SYSTEM_HANDLE_INFORMATION> lstHandles = new List<Win32API.SYSTEM_HANDLE_INFORMATION>();

            for (long lIndex = 0; lIndex < lHandleCount; lIndex++)
            {
                shHandle = new Win32API.SYSTEM_HANDLE_INFORMATION();
                if (Is64Bits())
                {
                    shHandle = (Win32API.SYSTEM_HANDLE_INFORMATION)Marshal.PtrToStructure(ipHandle, shHandle.GetType());
                    ipHandle = new IntPtr(ipHandle.ToInt64() + Marshal.SizeOf(shHandle) + 8);
                }
                else
                {
                    ipHandle = new IntPtr(ipHandle.ToInt64() + Marshal.SizeOf(shHandle));
                    shHandle = (Win32API.SYSTEM_HANDLE_INFORMATION)Marshal.PtrToStructure(ipHandle, shHandle.GetType());
                }

                if (process != null)
                {
                    if (shHandle.ProcessID != process.Id) continue;
                }

                string strObjectTypeName = "";
                if (IN_strObjectTypeName != null){
                     strObjectTypeName = getObjectTypeName(shHandle, Process.GetProcessById(shHandle.ProcessID));
                    if (strObjectTypeName != IN_strObjectTypeName) continue;
                }

                string strObjectName = "";
                if (IN_strObjectName != null){
                     strObjectName = getObjectName(shHandle, Process.GetProcessById(shHandle.ProcessID));
                    if (strObjectName != IN_strObjectName) continue;
                }

                string strObjectTypeName2 = getObjectTypeName(shHandle, Process.GetProcessById(shHandle.ProcessID));
                string strObjectName2 = getObjectName(shHandle, Process.GetProcessById(shHandle.ProcessID));
                Console.WriteLine("{0}   {1}   {2}", shHandle.ProcessID, strObjectTypeName2, strObjectName2);

                lstHandles.Add(shHandle);
            }
            return lstHandles;
        }

        public static bool Is64Bits()
        {
            return Marshal.SizeOf(typeof(IntPtr)) == 8 ? true : false;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            String MutexName = "MSCTF.Asm.MutexDefault1";
            String ProcessName = "notepad";

            try
            {
                Process process = Process.GetProcessesByName(ProcessName)[0];
                var handles = Win32Processes.GetHandles(process, "Mutant", "\\Sessions\\1\\BaseNamedObjects\\" + MutexName);
                if (handles.Count == 0) throw new System.ArgumentException("NoMutex", "original");
                foreach (var handle in handles)
                {
                    IntPtr ipHandle = IntPtr.Zero;
                    if (!Win32API.DuplicateHandle(Process.GetProcessById(handle.ProcessID).Handle, handle.Handle, Win32API.GetCurrentProcess(), out ipHandle, 0, false, Win32API.DUPLICATE_CLOSE_SOURCE))
                        Console.WriteLine("DuplicateHandle() failed, error = {0}", Marshal.GetLastWin32Error());

                    Console.WriteLine("Mutex was killed");
                }
            }
            catch (IndexOutOfRangeException)
            {
                Console.WriteLine("The process name '{0}' is not currently running", ProcessName);
            }
            catch (ArgumentException)
            {
                Console.WriteLine("The Mutex '{0}' was not found in the process '{1}'", MutexName, ProcessName);
            }
            Console.ReadLine();
        }
    }
}

评论

You need elevated privileges for that - especially DEBUG privilege.

See:

  • Manipulate Privileges in Managed Code Reliably, Securely, and Efficiently (MSDN)
  • Debug Privilege (MSDN)
  • The Windows Access Control Model Part 3
  • Simon Mourier's answer to Stack Overflow question How to enable the SeCreateGlobalPrivilege in .NET without resorting to P/Invoke or reflection?
  • ObjectSecurity Methods (MSDN)

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • C++/Linux 中的系统范围全局变量/信号量/互斥锁?(System-wide global variable / semaphore / mutex in C++/Linux?)
    问题 是否可以在 Linux 上的 C++ 中创建系统范围的全局变量/信号量/互斥锁? 原因如下:我有一个系统,它经常在不相关的数据上运行相同软件的多个副本。 通常有 4 个作业,每个作业运行相同的软件。 该软件有一个小部分,它创建了一个占用大量内存的巨大图形; 在该部分之外,内存使用量适中。 有时会发生 2 个作业同时命中同一个内存饥渴部分并且整个系统开始交换的情况。 因此,我们希望通过在不同作业之间创建诸如临界区互斥锁之类的东西来防止这种情况发生,以便其中一次分配大量内存。 如果这些是同一作业的线程,则 pthread 锁将完成这项工作。 在不同的工作之间实现这种互斥锁的好方法是什么? 回答1 如果您可以让所有进程就通用名称达成一致,则可以使用命名信号量。 命名信号量由形式/somename的名称/somename ; 即,最多 NAME_MAX-4(即 251)个字符的以空字符结尾的字符串,由一个起始斜杠和一个或多个字符组成,其中没有一个是斜杠。 通过将相同的名称传递给sem_open(3)两个进程可以对同名的信号量进行操作。 回答2 对于进程间互斥,可以使用文件锁定。 使用 linux,代码就像通过调用 flock 来保护临界区一样简单。 int fd_lock = open(LOCK_FILE, O_CREAT); flock(fd_lock, LOCK_EX); //
  • AbandonedMutexException for system mutex 在第 1 次运行终止时未在第 2 次运行时捕获(AbandonedMutexException for system mutex not caught on 2nd run when 1st run killed)
    问题 我创建了以下测试程序: static void Main(string[] args) { using (var mutex = new Mutex(false, "foobar")) { Console.WriteLine("Created mutex"); try { try { if (!mutex.WaitOne(TimeSpan.FromSeconds(5), false)) { Console.WriteLine("Unable to acquire mutex"); Environment.Exit(0); } } catch (AbandonedMutexException) { Console.WriteLine("Mutex was abandoned"); } Console.WriteLine("Acquired mutex - sleeping 10 seconds"); Thread.Sleep(10000); } finally { mutex.ReleaseMutex(); Console.WriteLine("Released mutex"); } } 这个想法是我运行程序,当线程休眠 10 秒时,我通过任务管理器终止进程。 下次运行该进程时,我希望在WaitOne()调用中会捕获AbandonedMutexException 。
  • 深入理解 Android 内核设计思想(一)进程间通信与同步机制
    对冗余挑拣重点,对重点深入补充 以更易理解且简洁的方式记录呈现 不是杂乱无章的笔记,而是原书的精简版… 1. 进程间通信的经典实现 1.共享内存 2.管道 3.UNIX Domain Socket 4.Remote Procedure Calls 2. 同步机制的经典实现 1.信号量 2.Mutex 3.管程 4.Linux Futex 3. Android 中的进程间同步机制 1.进程间同步 Mutex 2.条件判断 Condition 3.加解锁的自动化操作 Autolock 4.Mutex+Autolock+Condition 示例 4. 最后 进程间通信的经典实现 进程间通信(Inter-process communication,IPC)指运行在不同进程中的若干线程间的数据交换,可发生在一台机器上,也可通过网络跨机器实现。 共享内存、管道、UNIX Domain Socket 和 RPC 因高效稳定的优点几乎被应用在所有操作系统中。 共享内存 共享内存是一种常用的进程间通信机制,不同进程可以直接共享访问同一块内存区域,避免了数据拷贝,速度较快。实现步骤如下: 1. 创建内存共享区 Linux 通过 shmget 方法创建与特定 key 关联的共享内存块: //返回共享内存块的唯一 Id 标识 int shmget(key_t key, size_t size, int
  • 在 .net 中制作单实例应用程序的最佳方法是什么? [复制](What is the best way to make a single instance application in .net? [duplicate])
    问题 这个问题在这里已经有了答案: 11 年前关闭。 可能的重复: 创建单实例应用程序的正确方法是什么? 防止.NET 中给定应用程序的多个实例? 我是否检查是否存在另一个同名的进程? (如果用户没有权限这样做怎么办?) 将文件写入磁盘并在退出前将其删除? (异常终止呢?) 这样做的最佳做法是什么? 回答1 您可以使用互斥锁。 bool firstInstance = true; using (Mutex mutex = new Mutex(true, "MyApplicationName", out firstInstance)) { if (firstInstance) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm()); } else { // Another instance loaded } } 回答2 您可以使用Process类的GetProcessesByName方法查找另一个同名正在运行的进程,如果找到则退出。 回答3 通常,命名的互斥锁效果最好。 这是一个例子的链接:http://www.iridescence.no/post
  • 如何同步三个线程?(How can I synchronize three threads?)
    问题 我的应用程序由主进程和两个线程组成,所有线程都同时运行并使用三个 fifo 队列: fifo-q 是 Qmain、Q1 和 Q2。 在内部,每个队列都使用一个计数器,当一个项目放入队列时该计数器递增,当一个项目从队列中“获取”时该计数器递减。 处理涉及两个线程, QMaster,从Q1和Q2得到,放入Qmain, 监视器,进入第二季度, 以及从 Qmain 获取并放入 Q1 的主进程。 QMaster 线程循环连续检查 Q1 和 Q2 的计数,如果 q 中有任何项目,则获取它们并将它们放入 Qmain。 Monitor-thread 循环从外部获取数据,打包并放入 Q2。 应用程序的主进程还运行一个循环来检查 Qmain 的计数,如果有任何项目,则在循环的每次迭代中从 Qmain 获取一个项目并进一步处理它。 在此处理过程中,它偶尔会将一个项目放入 Q1 以供稍后处理(当它依次从 Qmain 获取时)。 问题: 我已经实现了上述所有内容,它在随机(短)时间内工作,然后挂起。 我已经设法确定在 fifo-q 计数的递增/递减中发生崩溃的来源(它可能发生在任何一个中)。 我试过的: 使用三个互斥锁:QMAIN_LOCK、Q1_LOCK 和 Q2_LOCK,只要在相关的 fifo-q 上完成任何 get/put 操作,我就会锁定它们。 结果:应用程序无法运行,只是挂起。
  • 平台无关的文件锁定?(Platform independent file locking?)
    问题 我正在运行一项计算量非常大的科学工作,它时不时地输出结果。 这项工作基本上只是模拟一堆相同的东西,所以它被分成几台使用不同操作系统的计算机。 我想将所有这些实例的输出定向到同一个文件,因为所有计算机都可以通过 NFS/Samba 看到同一个文件系统。 以下是限制条件: 必须允许安全的并发追加。 如果另一台计算机上的某个其他实例当前正在附加到文件,则必须阻止。 性能不计。 每个实例的 I/O 仅为每分钟几个字节。 简单确实很重要。 这样做的全部意义(除了纯粹的好奇)是,我可以停止让每个实例写入不同的文件并手动将这些文件合并在一起。 不得依赖于文件系统的详细信息。 必须使用 NFS 或 Samba 挂载上的未知文件系统。 我使用的语言是 D,以防万一。 我看过了,标准库中似乎没有任何内容可以做到这一点。 D-specific 和一般的、与语言无关的答案都是完全可以接受和赞赏的。 回答1 通过 NFS,您会面临客户端缓存和陈旧数据的一些问题。 我之前写过一个独立于操作系统的锁模块来在 NFS 上工作。 创建 [datafile].lock 文件的简单想法不适用于 NFS。 解决这个问题的基本思想是创建一个锁定文件 [datafile].lock,如果存在则表示文件未被锁定,并且想要获取锁定的进程将文件重命名为不同的名称,如 [datafile].lock.[主机名].[pid]。
  • boost::named_mutex:最后一个进程关闭时安全清理(boost::named_mutex: Safely cleaning up when last process closes)
    问题 我有一个资源,我需要保护对一个进程内和多个进程的访问。 我通过boost::interprocess:named_recursive_mutex创建了一个命名的互斥体来管理这个,它工作得很好。 #include <boost/interprocess/sync/named_recursive_mutex.hpp> boost::interprocess::named_recursive_mutex mut( boost::interprocess::open_or_create, "MY_SHARED_MUTEX_123"); 但是,据我所知,这最终应该通过remove() ,即: mut.remove("MY_SHARED_MUTEX"); 然而,这个调用似乎完全破坏了互斥锁,而不是检查/减少引用计数,所以当我知道没有其他进程正在使用它时,我试图找到一种安全的方法来发出remove()调用。 我也可以通过 boost 创建一块共享内存,但这似乎也没有共享引用计数。 我在 SO 上发现了一个类似的问题,但接受的答案似乎不足以满足我的需求,因为它只是指“boost docs”,但没有给出关于何时可以使用remove()的明确指示安全发出。 当我确定访问它的最后一个进程已经关闭或可能崩溃时,如何安全地清理这个命名的互斥锁? 谢谢你。 回答1 据我所知,没有任何引用计数支持。
  • enable_shared_from_this 与直接分配(enable_shared_from_this Vs Direct Assignment)
    问题 我为什么要使用 enable_shared_from_this ,因为我也可以通过普通分配获得相同的效果。 struct A : std::enable_shared_from_this<A> { std::shared_ptr<A> getptr() { return shared_from_this(); } }; int main () { // What is the differentce between this code std::shared_ptr<A> p1 = make_shared<A>(); std::shared_ptr<A> p2 = p1->getptr(); // Vs this std::shared_ptr<A> p1 = make_shared<A>(); std::shared_ptr<A> p2 = p1; } 回答1 因为你无法获得“相同”的效果”,至少不是你可能想到的那种。 发布的代码方法没有区别,正是因为A继承自std::enable_shared_from_this<A> 。 p1 和 p2 都是引用同一个具体对象的 shared_ptr 对象(假设只有其中一个部分是为您的测试编译的,否则您会在 id 名称重用时出错)。 std::enable_shared_from_this<T>允许你获得std::shared_ptr
  • 如何判断我的程序的另一个实例是否已经在运行?(How can I tell if another instance of my program is already running?)
    问题 如何判断我的程序的一个实例是否正在运行? 我以为我可以用数据文件来做到这一点,但那会很混乱:( 我要这样做是因为我只希望一次打开1个实例。 回答1 您可以创建一个信号灯并停止执行(将代码放入* .dpr文件中),然后将正在运行的应用程序显示在屏幕上。 var Semafor: THandle; begin { Don't start twice ... if already running bring this instance to front } Semafor := CreateSemaphore(nil, 0, 1, 'MY_APPLICATION_IS_RUNNING'); if ((Semafor <> 0) and { application is already running } (GetLastError = ERROR_ALREADY_EXISTS)) then begin RestoreWindow('TMyApplication'); CloseHandle(Semafor); Halt; end; Application.CreateForm(....); Application.Initialize; Application.Run; CloseHandle(Semafor); end; 编辑(添加了RestoreWindow方法):
  • 使用 Win API 确定可执行文件的实例是否已在运行(Use Win API to determine if an instance of an executable is already running)
    问题 我需要确保只有 1 个 C++ 应用程序实例正在运行。 使用 Win API 我该怎么做; 检索有关我当前应用程序的信息? GetCurrentProcess()会给我一个关于我的应用程序的句柄,我如何检索有关它的信息为用户检索所有正在运行的进程的列表? EnumProcesses()给出了一个列表,但似乎需要一个预先分配的缓冲区,那么我如何找出当前正在运行的进程数? 我需要将我的服务器的 exe 名称与正在运行的进程进行比较,如果我发现不止一个,则会引发错误 注意:我不能使用任何 boost 库,而且我对使用类似帖子中看到的mutex不感兴趣。 回答1 您可以使用CreateMutex函数创建一个系统范围的互斥锁来表示您的进程是否正在运行。 如果进程已经在运行,它将返回ERROR_ALREADY_EXISTS : (void)::CreateMutex( NULL, TRUE, TEXT( "My_Special_Invokation_Test_Mutex" ) ); switch ( ::GetLastError() ) { case ERROR_SUCCESS: // Process was not running already break; case ERROR_ALREADY_EXISTS: // Process is running already break
  • 并发程序中的I / O(I/O in concurrent program)
    问题 我正在开发一个并发程序; 它有两个线程,一个线程侦听来自服务器的消息,另一个线程向它发送消息。 我需要从用户那里获取命令(使用cin?)并同时显示来自服务器的消息。 我该如何处理这种情况? 问题是,如果在收到消息时我正在从用户读取命令,则用户的输入会与其他内容混淆。 提前致谢 回答1 一些替代方案 让您的命令转储自上次调用命令以来发生的所有消息。 这样,输出是有限的。 让cli命令连续监视所有流量,直到按下ctrl-c(或其他组合键),然后它才返回到应用程序的cli提示符。 让您的cli命令将数据发送到文件并使用tail类型的工具对其进行监视 回答2 我采用了旧的示例代码,并尝试将其转换为MCVE。 (“最小”不一定表示“空头”,对吗?) 这是“外壳”的非常简单的概念,它支持一个线程进行输入,而多个线程可以进行输出。 键盘输入是不回声的。 这是不可携带的。 因此,我提供了功能getChar()两种实现-一种用于MS Windows,另一种用于非MS Windows(实际上仅考虑* ix OS)。 后者受到SO的“强烈启发”:如何在Linux中实现C的getch()函数? 输入字符存储在std::string 。 输出擦除提示和当前输入文本(重复"\b \b"的输出),打印输出文本(包括换行符),然后再次打印提示和当前输入缓冲区。 输出经过互斥保护以授予线程安全性。
  • Win32:如何获取拥有互斥锁的进程/线程?(Win32: How to get the process/thread that owns a mutex?)
    问题 我正在开发一个在任何给定时间仅必须存在一个实例的应用程序。 有几种方法可以实现此目的: 检查正在运行的进程中是否存在一个与我们的EXE名称匹配的文件(不可靠) 查找主窗口(不可靠,而且我并不总是有主窗口) 创建具有唯一名称(GUID)的互斥锁 在我看来,互斥锁选项最可靠,最优雅。 但是,在第二个实例终止之前,我想向已运行的实例发布消息。 为此,我需要拥有互斥量的线程(或进程)的句柄。 但是,似乎没有API函数可以获取给定互斥锁的创建者/所有者。 我只是俯瞰它吗? 还有另一种方法可以访问该线程/进程吗? 还有另一种方法可以解决这个问题吗? 更新:这个家伙只是向所有正在运行的进程广播一条消息。 我想这是可能的,但是我真的不喜欢它。 回答1 我认为没有一种简单的方法可以解决Mutex的实际所有者,但是拥有该Mutex的过程可以创建其他次级项目,这些项目的生命周期与之相关。 有很多机制都适合在没有主窗口的情况下跨进程进行回调。 在COM运行对象表中注册一个对象。 无法获得Mutex所有权的客户端可以通过ROT查找所有者,然后回叫所有者。 File Moniker应该适合在这里注册。 创建一个共享内存块,其中包含所有者进程的位置详细信息。 从那里,将可以接收Windows消息的线程的进程句柄和线程句柄写入缓冲区,然后使用PostThreadMessage()发送通知。
  • Redis源码解析(24) BIO机制探究
    本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本作品 (李兆龙 博文, 由 李兆龙 创作),由 李兆龙 确认,转载请注明版权。 文章目录 引言单线程 or 多线程异步操作哪些地方用到了多线程BIO机制lazyfree机制网络IO总结 引言 时隔十个月再次提笔去探究Redis相关的东西,心中还是有一点激动的。最近打算用两到三篇文章来再过一下Redis相关的东西,不但是对以前遗漏知识点的一点补充,也是对最近这一段时间复习Redis画上一个句号。 这篇文章主要是想说一个问题,Redis到底是单线程还是多线程?简单在各大平台搜索了一下这个问题,发现至少百分之七十的文章基本上是没有一丝价值,但是其中也不乏不少好文章。本篇文章就基于前人的讨论,再加上自己的理解,来探讨一下这个问题。不过因为看的源码版本太低,一些部分的讨论没办法附以代码。 单线程 or 多线程 我们到底什么时候该使用多线程呢?在[1]中描述的很清楚,使用多线程有两个原因,即利用多核效率和关注点分离。与此相反不使用多线程的原因就是受益比不上回报的时候。 先抛出答案,Redis使用多线程,而不是单线程。当然这里的意思与我们平时聊天中默认的想法有一点出入,平时我们去说WebServer单线程还是多线程的时候,我们实际讨论的是worker线程到底是单还多
  • 为什么不能保证 memcpy 对于非 POD 类型是安全的?(Why isn't memcpy guaranteed to be safe for non-POD types?)
    问题 我从 SO 上发布的几个问题中读到了这一段。 我不太明白为什么不能保证memcpy对于非 POD 类型是安全的。 我的理解是memcpy只是一个位的副本。 以下是来自标准的报价 对于POD类型T任何对象(基类子对象除外),无论该对象是否持有T类型的有效值,构成该对象的底层字节 (1.7) 都可以复制到char或unsigned char数组中unsigned char .41) 如果char或unsigned char数组的内容被复制回对象,则该对象随后应保持其原始值。 # define N sizeof (T) char buf[N]; T obj ; // obj initialized to its original value std :: memcpy (buf , & obj , N); // between these two calls to std::memcpy, // obj might be modified std :: memcpy (& obj , buf , N); // at this point, each subobject of obj of // scalar type holds its original value 回答1 尝试按位复制std::shared_ptr<> 。 您可能会发现您的程序经常在您面前失败。
  • C++面试基础知识汇总
    C++面试基础知识汇总 本篇文章用于C++面试基础知识复习,不断更新。自用。 文章目录 C++面试基础知识汇总1.new/delete/malloc/free关系2.delete与delete[]的区别3.extern关键字作用4.static关键字作用5.volatile6.const*7.C++多态性与虚函数表*8.指针和引用的区别9.指针与数组10.智能指针11.C++四种类型转换12.结构体内存对齐13.右值引用14.类管理内存的方式15.可重入函数与不可重入函数16.内联函数、宏定义17.C++程序五大内存分区: 18.C++11线程的几种锁互斥锁条件锁自旋锁读写锁 19.乐观锁、悲观锁20.堆与栈21.C++内存管理22.struct和class的区别23.成员初始化列表24.C++的调用惯例(函数调用)25.可执行文件的编译过程26.set,map和vector的插入复杂度27.free和delete释放后的内存系统会马上回收吗?28.C++11新特性Lambda表达式自动类型推导auto和decltypedeleted函数与defaulted函数nullptr右值引用标准库更新 数据结构部分map和unordered_map红黑树详解哈希表vector 操作系统部分进程和线程的联系和区别进程通信详解 1.new/delete/malloc/free关系 new
  • 从多线程程序中安全地删除对象(Delete an object securely from a multi-threaded program)
    问题 免责声明:Boost 和 C++11 都不允许。 我有一个程序,我在其中创建了一个Foo实例,并在多个线程中对其进行操作。 然后我想安全地删除它,这样那些线程就不会陷入分段错误。 我已经向Foo添加了一个互斥锁成员,并在每次线程函数运行时锁定它。 为了不同的线程不相互冲突。 class Foo { public: pthread_mutex_t mutex; }; void* thread ( void* fooPtr ) { Foo* fooPointer = (Foo*) fooPtr; while ( 1 ) { if ( fooPointer ) { pthread_mutex_lock ( &fooPointer->mutex ); /* some code, involving fooPointer */ pthread_mutex_unlock ( &fooPointer->mutex ); } else { pthread_exit ( NULL ); } } } 现在我想安全地删除foo以便线程中不会发生错误。 我已经向Foo添加了一个析构函数: Foo::~Foo() { pthread_mutex_lock ( &mutex ); } 现在,在所有线程完成当前循环之前,不会删除该对象。 问题是:删除实例后,互斥锁会解锁吗? 删除实例后所有线程都会结束吗?
  • “制作单实例应用程序”这是做什么的?("make single instance application" what does this do?)
    问题 在 vb 2008 express 中,此选项在应用程序属性下可用。 有谁知道它的功能是什么? 它是否使它不可能同时打开两个实例? 回答1 它是否使它不可能同时打开两个实例? 是的。 回答2 为什么不直接使用互斥锁? 这就是 MS 的建议,我已经使用它很多年了,没有任何问题。 Public Class Form1 Private objMutex As System.Threading.Mutex Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 'Check to prevent running twice objMutex = New System.Threading.Mutex(False, "MyApplicationName") If objMutex.WaitOne(0, False) = False Then objMutex.Close() objMutex = Nothing MessageBox.Show("Another instance is already running!") End End If 'If you get to this point it's frist instance End Sub End
  • 基于小熊派的HarmonyOS鸿蒙开发教程——内核篇
    复习时间:貌似很遥远呀!(未定期) 基于小熊派的鸿蒙开发内核篇 一、CMSIS-RTOS2接口二、HarmonyOS内核开发—任务管理三、HarmonyOS内核开发—定时器管理定时器基本概念定时器运行机制定时器创建实现实验拓展 四、HarmonyOS内核开发—信号量信号量基本概念信号量运行机制信号量功能实现实验拓展 五、HarmonyOS内核开发—事件管理事件管理基本概念事件管理运行机制事件管理功能实现实验拓展 六、HarmonyOS内核开发—互斥锁互斥锁基本概念互斥锁运行机制互斥锁功能实现拓验拓展 七、HarmonyOS内核开发—消息队列1、消息队列基本概念2、消息队列运行机制3、消息队列功能实现4、实验拓展 一、CMSIS-RTOS2接口 Cortex微控制器软件接口标准,Cortex-M系列的RTOS接口,为需要RTOS的软件组件提供了标准化API访问内核或外设。更多API参考: https://arm-software.github.io/CMSIS_5/RTOS2/html/index.html 二、HarmonyOS内核开发—任务管理 三、HarmonyOS内核开发—定时器管理 定时器基本概念 是基于系统Tick时钟中断且由软件来模拟的定时器,当经过设定的Tick时钟计数值后会触发用户定义的回调函数。定时精度与系统Tick时钟的周期有关。 定时器运行机制 使用系统队列
  • 快速安全删除MySQL大表
    目录 一、表删除过程 1. buffer pool清除 2. 删除表相关的磁盘文件 二、创建硬链接 三、删除表 四、删除文件释放空间 参考: 在一个高负载的生产数据库上删除大表需要一些技巧,倘若直接drop table,将产生大量磁盘I/O,严重的会卡库,这是高可用服务所不能接受的。要优化删除表,需要了解其内部执行过程。 一、表删除过程 表删除原理上分为内存和磁盘两部分操作: 清除表相关的buffer pool页面。删除表相关的磁盘文件。 1. buffer pool清除 删除表时,MySQL会将表在buffer pool中对应的页面清除,这个过程中会对buffer pool上一个全局排它锁。在MySQL 5.5.23以后的版本,实现了一个lazy drop table方式,以减轻清理内存结构的操作对系统吞吐量产生的波动,具体的过程: 1. 持有buffer pool mutex; 2. 持有buffer pool中的flush list mutex; 3. 开始扫描flush list; 1. 如果dirty page属于drop table,那么就直接从flush list中remove掉; 2. 如果删除的page个数超过了#define BUF_LRU_DROP_SEARCH_SIZE 1024 这个数目的话,释放buffer pool mutex,flush list
  • 如何确保仅Java应用程序的单个实例在运行?(How to make sure that only a single instance of a Java application is running?)
    问题 我希望我的应用程序检查自身是否已在运行另一个版本。 例如, demo.jar启动,用户单击以再次运行它,但是第二个实例意识到“哦,等等,已经在运行demo.jar ”。 并退出并显示一条消息。 回答1 您所寻找的内容可能最好用锁定文件来完成。 锁定文件仅指具有预定义位置的文件,并且该文件的存在是您的互斥量。 测试程序启动时该文件是否存在,如果存在,请立即退出。 在已知位置创建文件。 如果您的程序正常退出,请删除锁定文件。 最好的办法是,如果您还可以使用pid(进程ID)填充文件,以便可以检测到异常退出,但这些异常退出并没有删除文件,而是特定于操作系统的。 回答2 强制使用ServerSocket锁运行程序的一个实例 Java代码。 将其放入一个名为Main.java的文件中: import java.net.*; import java.io.*; public class Main{ public static void main(String args[]){ ServerSocket socket = null; try { socket = new ServerSocket(34567); System.out.println("Doing hard work for 100 seconds"); try{ Thread.sleep(100000); } catch